<!DOCTYPE html>



  


<html class="theme-next mist use-motion" lang="zh-Hans">
<head><meta name="generator" content="Hexo 3.8.0">
  <meta name="google-site-verification" content="-YPbgjltFVFljoCm04Ktk0m38A8CkQxpifuKVZXtawA">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">






















<link href="/blog/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css">

<link href="/blog/css/main.css?v=5.1.4" rel="stylesheet" type="text/css">


  <link rel="apple-touch-icon" sizes="180x180" href="/blog/images/avatar.gif?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/blog/images/avatar.gif?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/blog/images/avatar.gif?v=5.1.4">


  <link rel="mask-icon" href="/blog/images/avatar.gif?v=5.1.4" color="#222">





  <meta name="keywords" content="java,设计模式,">





  <link rel="alternate" href="/blog/atom.xml" title="lfagon" type="application/atom+xml">






<meta name="description" content="创建型模式： 对象实例化的模式，创建型模式用于解耦对象的实例化过程 建造者模式 建造者模式主要为了解决那些类的构造函数需要传入太多参数所应用的一中模式。因为太多参数不容易阅读，而且容易出错。采用了建造者模式之后，更加精炼，而且不需要的参数都无需设置。 就拿电脑举例吧 Computer是由（CPU，Graphics，MainBoard，Power，Memory，Screen) 构成的，且它们都具有如">
<meta name="keywords" content="java,设计模式">
<meta property="og:type" content="article">
<meta property="og:title" content="java设计模式">
<meta property="og:url" content="http://lfagon.gitee.io/blog/2019/05/16/java设计模式/index.html">
<meta property="og:site_name" content="lfagon">
<meta property="og:description" content="创建型模式： 对象实例化的模式，创建型模式用于解耦对象的实例化过程 建造者模式 建造者模式主要为了解决那些类的构造函数需要传入太多参数所应用的一中模式。因为太多参数不容易阅读，而且容易出错。采用了建造者模式之后，更加精炼，而且不需要的参数都无需设置。 就拿电脑举例吧 Computer是由（CPU，Graphics，MainBoard，Power，Memory，Screen) 构成的，且它们都具有如">
<meta property="og:locale" content="zh-Hans">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20181122135133417.png">
<meta property="og:updated_time" content="2019-06-21T07:03:10.174Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="java设计模式">
<meta name="twitter:description" content="创建型模式： 对象实例化的模式，创建型模式用于解耦对象的实例化过程 建造者模式 建造者模式主要为了解决那些类的构造函数需要传入太多参数所应用的一中模式。因为太多参数不容易阅读，而且容易出错。采用了建造者模式之后，更加精炼，而且不需要的参数都无需设置。 就拿电脑举例吧 Computer是由（CPU，Graphics，MainBoard，Power，Memory，Screen) 构成的，且它们都具有如">
<meta name="twitter:image" content="https://img-blog.csdnimg.cn/20181122135133417.png">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/blog/',
    scheme: 'Mist',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":true,"onmobile":false},
    fancybox: false,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="http://lfagon.gitee.io/blog/2019/05/16/java设计模式/">





  <title>java设计模式 | lfagon</title>
  








  <!-- Global site tag (gtag.js) - Google Analytics -->
  <script async src="https://www.googletagmanager.com/gtag/js?id=UA-139884627-1"></script>
  <script>
    window.dataLayer = window.dataLayer || [];
    function gtag(){dataLayer.push(arguments);}
    gtag('js', new Date());
    gtag('config', 'UA-139884627-1');
  </script>
</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">

    <div class="headband"></div>
    

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/blog/" class="brand" rel="start">
        <!-- <span class="logo-line-before"><i></i></span> -->
        <!-- <span class="site-title">lfagon</span> -->
	     <img src="/blog/images/logo.png">
        <!-- <span class="logo-line-after"><i></i></span> -->
      </a>
    </div>
      
        <h1 class="site-subtitle" itemprop="description">个人博客</h1>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/blog/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br>
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/blog/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br>
            
            标签
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/blog/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br>
            
            归档
          </a>
        </li>
      
        
        <li class="menu-item menu-item-top">
          <a href="/blog/top/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-signal"></i> <br>
            
            热门
          </a>
        </li>
      
        
        <li class="menu-item menu-item-schedule">
          <a href="/blog/schedule/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-calendar"></i> <br>
            
            日程表
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tracks">
          <a href="/blog/tracks" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-comment"></i> <br>
            
            留言
          </a>
        </li>
      

      
        <li class="menu-item menu-item-search">
          
            <a href="javascript:;" class="popup-trigger">
          
            
              <i class="menu-item-icon fa fa-search fa-fw"></i> <br>
            
            搜索
          </a>
        </li>
      
    </ul>
  

  
    <div class="site-search">
      
  <div class="popup search-popup local-search-popup">
  <div class="local-search-header clearfix">
    <span class="search-icon">
      <i class="fa fa-search"></i>
    </span>
    <span class="popup-btn-close">
      <i class="fa fa-times-circle"></i>
    </span>
    <div class="local-search-input-wrapper">
      <input autocomplete="off" placeholder="搜索..." spellcheck="false" type="text" id="local-search-input">
    </div>
  </div>
  <div id="local-search-result"></div>
</div>



    </div>
  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://lfagon.gitee.io/blog/blog/2019/05/16/java设计模式/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="付祥/lfagon">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/blog/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="lfagon">
    </span>

    
      <header class="post-header">

        
        
          <h2 class="post-title" itemprop="name headline">java设计模式</h2>
        

        <div class="post-meta">
	    
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <font color="blue"><i class="fa fa-calendar-o"></i></font>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2019-05-16T11:02:03+08:00">
                2019-05-16
              </time>
            

            
              <span class="post-meta-divider">|</span>
            

            
              <span class="post-meta-item-icon">
                 <font color="#40E0D0"><i class="fa fa-calendar-check-o"></i></font>
              </span>
              
                <span class="post-meta-item-text">更新于&#58;</span>
              
              <time title="更新于" itemprop="dateModified" datetime="2019-06-21T15:03:10+08:00">
                2019-06-21
              </time>
            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <font color="red"><i class="fa fa-folder-o"></i></font>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <font color="black"><span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/blog/categories/介绍/" itemprop="url" rel="index">
                    <span itemprop="name">介绍</span>
                  </a>
                </span></font>

                
                
              
            </span>
          

          
            
              <span class="post-comments-count">
                <span class="post-meta-divider">|</span>
                <span class="post-meta-item-icon">
                  <i class="fa fa-comment-o"></i>
                </span>
                <a href="/blog/2019/05/16/java设计模式/#comments" itemprop="discussionUrl">
                  <span class="post-comments-count gitment-comments-count" data-xid="/blog/2019/05/16/java设计模式/" itemprop="commentsCount"></span>
                </a>
              </span>
            
          

          
          

          

          
            <div class="post-wordcount">
              
                
                <span class="post-meta-item-icon">
                  <i class="fa fa-file-word-o"></i>
                </span>
                
                  <span class="post-meta-item-text">字数统计&#58;</span>
                
                <span title="字数统计">
                  18.3k
                </span>
              

              
                <span class="post-meta-divider">|</span>
              

              
                <span class="post-meta-item-icon">
                  <i class="fa fa-clock-o"></i>
                </span>
                
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                
                <span title="阅读时长">
                  82
                </span>
              
            </div>
          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <h1>创建型模式： 对象实例化的模式，创建型模式用于解耦对象的实例化过程</h1>
<h2>建造者模式</h2>
<p>建造者模式主要为了解决那些类的构造函数需要传入太多参数所应用的一中模式。因为太多参数不容易阅读，而且容易出错。采用了建造者模式之后，更加精炼，而且不需要的参数都无需设置。</p>
<p><strong>就拿电脑举例吧</strong></p>
<p>Computer是由（CPU，Graphics，MainBoard，Power，Memory，Screen) 构成的，<strong>且它们都具有如下方法，这里的内容，底下我全部用省略号代替</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line">构造器（String name)&#123;</span><br><span class="line">    <span class="keyword">this</span>.name=name;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function">String <span class="title">getName</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> name;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">setName</span><span class="params">(String name)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">this</span>.name = name;</span><br><span class="line">&#125;</span><br><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">toString</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> name;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<hr>
<h3>普通类建造者模式</h3>
<p><strong>CPU，Graphics，MainBoard，Power，Memory，Screen组件，省略号用上面声明出代替</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">CPU</span> </span>&#123;......&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Graphics</span> </span>&#123;......&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MainBoard</span> </span>&#123;......&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Power</span> </span>&#123;......&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Memory</span> </span>&#123;......&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Screen</span> </span>&#123;......&#125;</span><br></pre></td></tr></table></figure>
<p><strong>Computer,及ComputerBuilder</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Computer</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> CPU cpu;</span><br><span class="line">    <span class="keyword">private</span> Graphics graphics;</span><br><span class="line">    <span class="keyword">private</span> MainBoard mainBoard;</span><br><span class="line">    <span class="keyword">private</span> Memory memory;</span><br><span class="line">    <span class="keyword">private</span> Power power;</span><br><span class="line">    <span class="keyword">private</span> Screen screen;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 普通的创建对象的构造函数</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    Computer(CPU cpu, Graphics graphics, MainBoard mainBoard, Memory memory, Power power, Screen screen) &#123;</span><br><span class="line">        <span class="keyword">this</span>.cpu = cpu;</span><br><span class="line">        <span class="keyword">this</span>.graphics = graphics;</span><br><span class="line">        <span class="keyword">this</span>.mainBoard = mainBoard;</span><br><span class="line">        <span class="keyword">this</span>.memory = memory;</span><br><span class="line">        <span class="keyword">this</span>.power = power;</span><br><span class="line">        <span class="keyword">this</span>.screen = screen;</span><br><span class="line">    &#125;</span><br><span class="line">    ......</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ComputerBuilder</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> CPU cpu;</span><br><span class="line">    <span class="keyword">private</span> Graphics graphics;</span><br><span class="line">    <span class="keyword">private</span> MainBoard mainBoard;</span><br><span class="line">    <span class="keyword">private</span> Memory memory;</span><br><span class="line">    <span class="keyword">private</span> Power power;</span><br><span class="line">    <span class="keyword">private</span> Screen screen;</span><br><span class="line">    <span class="keyword">private</span> Computer computer;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> ComputerBuilder <span class="title">setCpu</span><span class="params">(CPU cpu)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.cpu = cpu;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> ComputerBuilder <span class="title">setGraphics</span><span class="params">(Graphics graphics)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.graphics = graphics;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> ComputerBuilder <span class="title">setMainBoard</span><span class="params">(MainBoard mainBoard)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.mainBoard = mainBoard;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> ComputerBuilder <span class="title">setMemory</span><span class="params">(Memory memory)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.memory = memory;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> ComputerBuilder <span class="title">setPower</span><span class="params">(Power power)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.power = power;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> ComputerBuilder <span class="title">setScreen</span><span class="params">(Screen screen)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.screen = screen;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> Computer <span class="title">build</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> Computer(cpu, graphics, mainBoard, memory, power, screen);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行……</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestBuildComputer</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"创建一个默认配置电脑"</span>);</span><br><span class="line">        Computer computer = <span class="keyword">new</span> Computer. ComputerBuilder().build();</span><br><span class="line">        System.out.println(computer);</span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">"----"</span>);</span><br><span class="line">        System.out.println(<span class="string">"创建一个cpu为Intel的电脑，其他配置默认"</span>);</span><br><span class="line">        computer = <span class="keyword">new</span> Computer. ComputerBuilder()</span><br><span class="line">                .setCpu(<span class="keyword">new</span> CPU(<span class="string">"Intel"</span>)).build();</span><br><span class="line">        System.out.println(computer);</span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">"----"</span>);</span><br><span class="line">        System.out.println(<span class="string">"创建一个个性化的电脑"</span>);</span><br><span class="line">        computer = <span class="keyword">new</span> Computer. ComputerBuilder()</span><br><span class="line">                .setCpu(<span class="keyword">new</span> CPU(<span class="string">"Intel i7 7900k"</span>))</span><br><span class="line">                .setGraphicsCard(<span class="keyword">new</span> GraphicsCard(<span class="string">"NVDIA 1080ti"</span>))</span><br><span class="line">                .setMainBoard(<span class="keyword">new</span> MainBoard(<span class="string">"微星MSI"</span>))</span><br><span class="line">                .setMemory(<span class="keyword">new</span> Memory(<span class="string">"威刚16g"</span>))</span><br><span class="line">                .setPower(<span class="keyword">new</span> Power(<span class="string">"金河田"</span>))</span><br><span class="line">                .setScreen(<span class="keyword">new</span> Screen(<span class="string">"AOC"</span>))</span><br><span class="line">                .build();</span><br><span class="line">        System.out.println(computer);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这样的话这台电脑需要更换什么组件直接只要传进一部分，并不需要全部都传进去，其它的采用默认即可。</p>
<hr>
<h3>面向接口建造者模式</h3>
<p><strong>CPU，Graphics，MainBoard，Power，Memory，Screen接口</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">CPU</span></span>&#123;</span><br><span class="line">    <span class="function">String <span class="title">getName</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Graphics</span></span>&#123;</span><br><span class="line">    <span class="function">String <span class="title">getName</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">MainBoard</span></span>&#123;</span><br><span class="line">    <span class="function">String <span class="title">getName</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Power</span></span>&#123;</span><br><span class="line">    <span class="function">String <span class="title">getName</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Memory</span></span>&#123;</span><br><span class="line">    <span class="function">String <span class="title">getName</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Screen</span></span>&#123;</span><br><span class="line">    <span class="function">String <span class="title">getName</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>CPU，Graphics，MainBoard，Power，Memory，Screen各大品牌，省略号用上面声明出代替，并且实现了接口</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DefaultCPU</span> <span class="keyword">implements</span> <span class="title">CPU</span></span>&#123;......&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DefaultGraphics</span> <span class="keyword">implements</span> <span class="title">Graphics</span></span>&#123;......&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DefaultBoard</span> <span class="keyword">implements</span> <span class="title">MainBoard</span></span>&#123;......&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DefaultPower</span> <span class="keyword">implements</span> <span class="title">Power</span></span>&#123;......&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DefaultMemory</span> <span class="keyword">implements</span> <span class="title">Memory</span></span>&#123;......&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DefaultScreen</span> <span class="keyword">implements</span> <span class="title">Screen</span></span>&#123;......&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">IntelCPU</span> <span class="keyword">implements</span> <span class="title">CPU</span></span>&#123;......&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">AmdCPU</span> <span class="keyword">implements</span> <span class="title">CPU</span></span>&#123;......&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">NVDIAGraphics</span> <span class="keyword">implements</span> <span class="title">Graphics</span></span>&#123;......&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">AMDGraphics</span> <span class="keyword">implements</span> <span class="title">Graphics</span></span>&#123;......&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ASUSMainBoard</span> <span class="keyword">implements</span> <span class="title">MainBoard</span></span>&#123;......&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ColorfulMainBoard</span> <span class="keyword">implements</span> <span class="title">MainBoard</span></span>&#123;......&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">GoldenFieldPower</span> <span class="keyword">implements</span> <span class="title">Power</span></span>&#123;......&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">GalaxyFoldMemory</span> <span class="keyword">implements</span> <span class="title">Memory</span></span>&#123;......&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ASUSScreen</span> <span class="keyword">implements</span> <span class="title">Screen</span></span>&#123;......&#125;</span><br></pre></td></tr></table></figure>
<p><strong>Computer,及ComputerBuilder</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Computer</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> CPU cpu;</span><br><span class="line">    <span class="keyword">private</span> Graphics graphics;</span><br><span class="line">    <span class="keyword">private</span> MainBoard mainBoard;</span><br><span class="line">    <span class="keyword">private</span> Memory memory;</span><br><span class="line">    <span class="keyword">private</span> Power power;</span><br><span class="line">    <span class="keyword">private</span> Screen screen;</span><br><span class="line">    <span class="keyword">private</span> Computer computer;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 普通的创建对象的构造函数</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    Computer(CPU cpu, Graphics graphics, MainBoard mainBoard, Memory memory, Power power, Screen screen) &#123;</span><br><span class="line">        <span class="keyword">this</span>.cpu = cpu;</span><br><span class="line">        <span class="keyword">this</span>.graphics = graphics;</span><br><span class="line">        <span class="keyword">this</span>.mainBoard = mainBoard;</span><br><span class="line">        <span class="keyword">this</span>.memory = memory;</span><br><span class="line">        <span class="keyword">this</span>.power = power;</span><br><span class="line">        <span class="keyword">this</span>.screen = screen;</span><br><span class="line">    &#125;</span><br><span class="line">    ......</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ComputerBuilder</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> CPU cpu = <span class="keyword">new</span> DefaultCPU();</span><br><span class="line">    <span class="keyword">private</span> Graphics graphics = <span class="keyword">new</span> DefaultGraphics();</span><br><span class="line">    <span class="keyword">private</span> MainBoard mainBoard = <span class="keyword">new</span> DefaultMainBoard();</span><br><span class="line">    <span class="keyword">private</span> Memory memory = <span class="keyword">new</span> DefaultMemory();</span><br><span class="line">    <span class="keyword">private</span> Power power = <span class="keyword">new</span> DefaultPower();</span><br><span class="line">    <span class="keyword">private</span> Screen screen = <span class="keyword">new</span> DefaultScreen();</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> ComputerBuilder <span class="title">setCpu</span><span class="params">(CPU cpu)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.cpu = cpu;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> ComputerBuilder <span class="title">setGraphics</span><span class="params">(Graphics graphics)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.graphics = graphics;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> ComputerBuilder <span class="title">setMainBoard</span><span class="params">(MainBoard mainBoard)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.mainBoard = mainBoard;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> ComputerBuilder <span class="title">setMemory</span><span class="params">(Memory memory)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.memory = memory;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> ComputerBuilder <span class="title">setPower</span><span class="params">(Power power)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.power = power;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> ComputerBuilder <span class="title">setScreen</span><span class="params">(Screen screen)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.screen = screen;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Computer <span class="title">build</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> Computer(cpu, graphics, mainBoard, memory, power, screen);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行……</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestBuildComputer</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"创建一个默认配置电脑"</span>);</span><br><span class="line">        Computer computer = <span class="keyword">new</span> Computer. ComputerBuilder().build();</span><br><span class="line">        System.out.println(computer);</span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">"----"</span>);</span><br><span class="line">        System.out.println(<span class="string">"创建一个cpu为Intel的电脑，其他配置默认"</span>);</span><br><span class="line">        computer = <span class="keyword">new</span> Computer. ComputerBuilder()</span><br><span class="line">                .setCpu(<span class="keyword">new</span> IntelCPU()).build();</span><br><span class="line">        System.out.println(computer);</span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">"----"</span>);</span><br><span class="line">        System.out.println(<span class="string">"创建一个个性化的电脑"</span>);</span><br><span class="line">        computer = <span class="keyword">new</span> Computer. ComputerBuilder()</span><br><span class="line">                .setCpu(<span class="keyword">new</span> IntelCPU())</span><br><span class="line">                .setGraphicsCard(<span class="keyword">new</span> NVIDIAGraphics())</span><br><span class="line">                .setMainBoard(<span class="keyword">new</span> ASUSMainBoard())</span><br><span class="line">                .setMemory(<span class="keyword">new</span> GalaxyFoldMemory())</span><br><span class="line">                .setPower(<span class="keyword">new</span> GoldenFieldPower())</span><br><span class="line">                .setScreen(<span class="keyword">new</span> ASUSScreen())</span><br><span class="line">                .build();</span><br><span class="line">        System.out.println(computer);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>以上就是两种建造者模式，面向接口的建造者模式易于扩展，一般我们使用它。</p>
<h2>工厂模式</h2>
<p>这里就拿发射器和接受器来举例</p>
<ol>
<li>
<p>先定义发射器和接受器</p>
 <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Receive</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">receive</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Sender</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">send</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>写几个实现类</p>
 <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MailReceiver</span> <span class="keyword">implements</span> <span class="title">Receive</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">receive</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"mail接受方法执行"</span>);</span><br><span class="line">        System.out.println(<span class="string">"邮件接受"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SmsReceiver</span> <span class="keyword">implements</span> <span class="title">Receive</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">receive</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"sms发送方法接受"</span>);</span><br><span class="line">        System.out.println(<span class="string">"短信接受"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MailSender</span> <span class="keyword">implements</span> <span class="title">Sender</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">send</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"mail发送方法执行"</span>);</span><br><span class="line">        System.out.println(<span class="string">"邮件发送"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SmsSender</span> <span class="keyword">implements</span> <span class="title">Sender</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">send</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"sms发送方法执行"</span>);</span><br><span class="line">        System.out.println(<span class="string">"短信发送"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ol>
<p>以上就是我们要使用到的产品，接下来就是我们如何生产它们</p>
<hr>
<h3>简单工厂</h3>
<p><strong>指定类型构造，以发送为例</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SendFactorySimple</span> </span>&#123;</span><br><span class="line">    <span class="function">ISender <span class="title">produce</span><span class="params">(String type)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="string">"mail"</span>.equals(type))</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> MailSender();</span><br><span class="line">        <span class="keyword">else</span> <span class="keyword">if</span> (<span class="string">"sms"</span>.equals(type))</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> SmsSender();</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行……</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        SendFactorySimple sendFactory = <span class="keyword">new</span> SendFactorySimple();</span><br><span class="line">        ISender sender = sendFactory.produce(<span class="string">"sms"</span>);</span><br><span class="line">        sender.send();</span><br><span class="line">        sender = sendFactory.produce(<span class="string">"mail"</span>);</span><br><span class="line">        sender.send();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这样做的缺点就是必须要给定准确的名字，否则无法构建来</p>
<hr>
<p><strong>方法构造，以发送为例</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SendFactoryMethods</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> Sender <span class="title">produceMail</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> MailSender();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> Sender <span class="title">produceSms</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> SmsSender();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行……</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        SendFactoryMethods sendFactory = <span class="keyword">new</span> SendFactoryMethods();</span><br><span class="line">        Sender sender = sendFactory.produceSms();</span><br><span class="line">        sender.send();</span><br><span class="line">        sender = sendFactory.produceMail();</span><br><span class="line">        sender.send();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<hr>
<p><strong>静态方法构造，以发送为例</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SendFactoryStaticMethods</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Sender <span class="title">produceMail</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> MailSender();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Sender <span class="title">produceSms</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> SmsSender();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行……</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Sender sender = SendFactoryStaticMethods.produceSms();</span><br><span class="line">        sender.send();</span><br><span class="line">        sender = sendFactory.produceMail();</span><br><span class="line">        sender.send();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<hr>
<h3>抽象工厂</h3>
<p><strong>单一职责，即一个工厂只负责一个产品</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">SendProvider</span> </span>&#123;</span><br><span class="line">    <span class="function">Sender <span class="title">produce</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">ReceiveProvider</span> </span>&#123;</span><br><span class="line">    <span class="function">Receive <span class="title">produce</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SendFactory</span> <span class="keyword">implements</span> <span class="title">SendProvider</span> </span>&#123;</span><br><span class="line">    ......</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Sender <span class="title">produce</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(......) <span class="keyword">return</span> <span class="keyword">new</span> MailSender();</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> SmsSender();</span><br><span class="line">    &#125;</span><br><span class="line">    ......</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ReceiveFactory</span> <span class="keyword">implements</span> <span class="title">SendProvider</span> </span>&#123;</span><br><span class="line">    ......</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Receive <span class="title">produce</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(......)<span class="keyword">return</span> <span class="keyword">new</span> MailReceive();</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> SmsReceive();</span><br><span class="line">    &#125;</span><br><span class="line">    ......</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行……</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        SendProvider sendProvider=<span class="keyword">new</span> SendProvider(......);</span><br><span class="line">        Sender sender = sendProvider.produce();</span><br><span class="line">        sender.send();</span><br><span class="line"></span><br><span class="line">        ReceiveProvider receiveProvider=<span class="keyword">new</span> ReceiveProvider(......);</span><br><span class="line">        Receive receive = receiveProvider.produce();</span><br><span class="line">        receive.receive();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>产品链职责，即一个工厂负责一个产品链</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">MailProvider</span> </span>&#123;</span><br><span class="line">    <span class="function">Receive <span class="title">produceReceive</span><span class="params">()</span></span>;</span><br><span class="line">    <span class="function">Sender <span class="title">produceSender</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">SmsProvider</span> </span>&#123;</span><br><span class="line">    <span class="function">Receive <span class="title">produceReceive</span><span class="params">()</span></span>;</span><br><span class="line">    <span class="function">Sender <span class="title">produceSender</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MailFactory</span> <span class="keyword">implements</span> <span class="title">MailProvider</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Receive <span class="title">produceReceive</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> MailReceive();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Sender <span class="title">produceSender</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> MailSender();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SmsFactory</span> <span class="keyword">implements</span> <span class="title">SmsProvider</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Receive <span class="title">produceReceive</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> SmsReceive();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Sender <span class="title">produceSender</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> SmsSender();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行……</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        MailProvider mailProvider=<span class="keyword">new</span> MailProvider();</span><br><span class="line">        Sender sender = mailProvider.produceSender();</span><br><span class="line">        Receive receive = mailProvider.produceReceive();</span><br><span class="line">        sender.send();</span><br><span class="line">        receive.receive();</span><br><span class="line"></span><br><span class="line">        SmsProvider smsProvider=<span class="keyword">new</span> smsProvider();</span><br><span class="line">        Sender sender = smsProvider.produceSender();</span><br><span class="line">        Receive receive = smsProvider.produceReceive();</span><br><span class="line">        sender.send();</span><br><span class="line">        receive.receive();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2>原型模式</h2>
<p>原型就是给定一个对象，然后复制它<br>
①对象引用<br>
②栈区数据<br>
③堆区数据</p>
<p><strong>浅复制： 复制①②</strong></p>
<p>只是将所有的引用复制一遍，基本类型则是复制一遍，因为基本类型在栈中<br>
也就是说浅克隆只是复制栈中的内容</p>
<p><strong>深复制： 复制①②③</strong></p>
<p>将所有的引用和值都复制，就是完完全全的复制一份<br>
也就是复制栈和堆里的包括这个对象的所有内容</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ProtoType</span> <span class="keyword">implements</span> <span class="title">Cloneable</span>, <span class="title">Serializable</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">long</span> serialVersionUID = <span class="number">1L</span>;</span><br><span class="line">    <span class="keyword">private</span> String string;</span><br><span class="line">    <span class="keyword">private</span> Integer count;</span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="title">ProtoType</span><span class="params">(String string, <span class="keyword">int</span> count)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.string = string;</span><br><span class="line">        <span class="keyword">this</span>.count = count;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> CloneNotSupportedException, IOException, ClassNotFoundException </span>&#123;</span><br><span class="line">        ProtoType p = <span class="keyword">new</span> ProtoType(<span class="string">"我"</span>, <span class="number">10</span>);</span><br><span class="line">        ProtoType p1 = (ProtoType) p.clone();</span><br><span class="line">        System.out.println(<span class="string">"浅克隆"</span>);</span><br><span class="line">        System.out.println(<span class="string">"原对象==克隆对象 :"</span> + (p == p1));</span><br><span class="line">        System.out.println(<span class="string">"原对象。string==克隆对象。string :"</span> + (p.string == p1.string));</span><br><span class="line">        System.out.println(<span class="string">"原对象。int==克隆对象。int :"</span> + (p.count == p1.count));</span><br><span class="line">        ProtoType p2 = (ProtoType) p.deepClone();</span><br><span class="line">        System.out.println(<span class="string">"深克隆"</span>);</span><br><span class="line">        System.out.println(<span class="string">"原对象==克隆对象 :"</span> + (p == p2));</span><br><span class="line">        System.out.println(<span class="string">"原对象。string==克隆对象。string :"</span> + (p.string == p2.string));</span><br><span class="line">        System.out.println(<span class="string">"原对象。int==克隆对象。int :"</span> + (p.count == p2.count));</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">/* 浅复制 */</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> Object <span class="title">clone</span><span class="params">()</span> <span class="keyword">throws</span> CloneNotSupportedException </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">super</span>.clone();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">/* 深复制 */</span></span><br><span class="line">    <span class="function"><span class="keyword">private</span> Object <span class="title">deepClone</span><span class="params">()</span> <span class="keyword">throws</span> IOException, ClassNotFoundException </span>&#123;</span><br><span class="line"></span><br><span class="line">        <span class="comment">/* 写入当前对象的二进制流 */</span></span><br><span class="line">        ByteArrayOutputStream bos = <span class="keyword">new</span> ByteArrayOutputStream();</span><br><span class="line">        ObjectOutputStream oos = <span class="keyword">new</span> ObjectOutputStream(bos);</span><br><span class="line">        oos.writeObject(<span class="keyword">this</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">/* 读出二进制流产生的新对象 */</span></span><br><span class="line">        ByteArrayInputStream bis = <span class="keyword">new</span> ByteArrayInputStream(bos.toByteArray());</span><br><span class="line">        ObjectInputStream ois = <span class="keyword">new</span> ObjectInputStream(bis);</span><br><span class="line">        <span class="keyword">return</span> ois.readObject();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function">String <span class="title">getString</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> string;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">setString</span><span class="params">(String string)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.string = string;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">int</span> <span class="title">getCount</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> count;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">setCount</span><span class="params">(<span class="keyword">int</span> count)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.count = count;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2>单例模式</h2>
<p>顾名思义，它只有一个，无论怎么样，它都只有一个。</p>
<h3>懒汉模式</h3>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">LazySingletion</span> </span>&#123;</span><br><span class="line">    <span class="comment">//持有私有静态实例，防止被引用</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> LazySingletion lazySingletion = <span class="keyword">new</span> LazySingletion();</span><br><span class="line"></span><br><span class="line">    <span class="comment">//私有构造方法，防止被实例化</span></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="title">LazySingletion</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/* 静态工程方法，创建实例 */</span></span><br><span class="line">    <span class="function"><span class="keyword">static</span> LazySingletion <span class="title">getInstance</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> lazySingletion;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行……</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">TestLazySingletion</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        System.out.println(LazySingletion.getInstance());</span><br><span class="line">        System.out.println(LazySingletion.getInstance());</span><br><span class="line">        System.out.println(LazySingletion.getInstance() == LazySingletion.getInstance());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3>饿汉模式</h3>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">StarveSingletion</span> </span>&#123;</span><br><span class="line">    <span class="comment">/* 持有私有静态实例，防止被引用，此处赋值为null,目的是实现延迟加载 */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> StarveSingletionUp instance = <span class="keyword">null</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> Object lock = <span class="keyword">new</span> Object();</span><br><span class="line">    <span class="comment">//创建对象个数</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">volatile</span> <span class="keyword">int</span> count = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/* 私有构造方法，防止被实例化 */</span></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="title">StarveSingletion</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        count++;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">static</span> <span class="keyword">int</span> <span class="title">getInstanceCount</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> count;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/* 静态工程方法，创建实例 */</span></span><br><span class="line">    <span class="function"><span class="keyword">static</span> StarveSingletionUp <span class="title">getInstance</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (instance == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">synchronized</span> (lock) &#123;</span><br><span class="line">                <span class="comment">//如果不加这句if (instance == null) 在1000个线程情况还是会创建多个</span></span><br><span class="line">                <span class="keyword">if</span> (instance == <span class="keyword">null</span>) instance = <span class="keyword">new</span> StarveSingletionUp();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> instance;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/* 如果该对象被用于序列化，可以保证对象在序列化前后保持一致 */</span></span><br><span class="line">    <span class="function">Object <span class="title">readResolve</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> instance;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行……</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">TestStarveSingletion</span> </span>&#123;</span><br><span class="line">    <span class="keyword">static</span> Set&lt;StarveSingletion&gt; set = ConcurrentHashMap.newKeySet();</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">1000</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">new</span> Thread(<span class="keyword">new</span> Runnable() &#123;</span><br><span class="line">                <span class="meta">@Override</span></span><br><span class="line">                <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">                    set.add(StarveSingletionUp.getInstance());</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;).start();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">for</span> (StarveSingletionUp item : set) &#123;</span><br><span class="line">            System.out.println(item.toString());</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>饿汉模式写法深度解析</p>
<ol>
<li>
<p>不加同步块和不加二次判断</p>
 <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">static</span> StarveSingletion <span class="title">getInstance</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (instance == <span class="keyword">null</span>) &#123;</span><br><span class="line">            instance = <span class="keyword">new</span> StarveSingletionUp();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> instance;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>加上同步块，不加二次判断</p>
 <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">static</span> StarveSingletion <span class="title">getInstance</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (instance == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">synchronized</span> (lock) &#123;</span><br><span class="line">                instance = <span class="keyword">new</span> StarveSingletionUp();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> instance;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>加上同步块，加二次判断</p>
 <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">static</span> StarveSingletion <span class="title">getInstance</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (instance == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">synchronized</span> (lock) &#123;</span><br><span class="line">                <span class="keyword">if</span> (instance == <span class="keyword">null</span>) instance = <span class="keyword">new</span> StarveSingletionUp();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> instance;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
</li>
</ol>
<p>假设有非常多的线程，里面有A, B两个线程</p>
<p><strong>第一种</strong></p>
<ol>
<li>A线程先进入<code>if (instance == null)</code></li>
<li>但此时A线程还未创建对象，因此B线程也可以进入<code>if (instance == null)</code></li>
<li>A, B创建出多个对象</li>
</ol>
<p><strong>第二种</strong></p>
<ol>
<li>A线程先进入<code>if (instance == null)</code></li>
<li>但此时A线程还未创建对象，因此B线程也可以进入<code>if (instance == null)</code></li>
<li>A线程先获得锁进入synchronized块，那么B线程等待</li>
<li>当A线程创建对象完毕后，B线程获得锁进入synchronized块</li>
<li>B线程开始创建对象</li>
<li>A, B创建出多个对象</li>
</ol>
<p><strong>第三种</strong></p>
<ol>
<li>A线程先进入<code>if (instance == null)</code></li>
<li>但此时A线程还未创建对象，因此B线程也可以进入<code>if (instance == null)</code></li>
<li>A线程先获得锁进入synchronized块，那么B线程等待</li>
<li>A线程进行第二次判断<code>if (instance == null)</code>，A线程开始创建对象</li>
<li>当A线程创建对象完毕后，B线程获得锁进入synchronized块</li>
<li>B线程进行第二次判断<code>if (instance == null)</code>，失败，不进行创建对象</li>
<li>A, B创建出单个对象</li>
</ol>
<p><strong>第三种情况，B线程可能会空指针异常</strong></p>
<p>将synchronized关键字加在了内部，也就是说当调用的时候是不需要加锁的，只有在instance为null,并创建对象的时候才需要加锁，性能有一定的提升。但是，这样的情况，还是有可能有问题的。在Java指令中创建对象和赋值操作是分开进行的，也就是说instance = new Singleton(); 语句是分两步执行的：</p>
<ol>
<li>为新的Singleton实例分配空间，然后直接赋值给instance成员</li>
<li>初始化这个Singleton实例</li>
</ol>
<p>但是JVM并不保证这两个操作的先后顺序，也就是说有可能JVM会<br>
这样就可能出错了，我们以A，B两个线程为例：</p>
<ol>
<li>A，B线程同时进入了第一个if判断</li>
<li>A首先进入synchronized块，由于instance为null,所以它执行<code>instance = new Singleton();</code>语句</li>
<li>由于JVM内部的优化机制，JVM先画出了一些分配给Singleton实例的空白内存，并赋值给instance成员（注意此时JVM没有开始初始化这个实例），然后A离开了synchronized块</li>
<li>B进入synchronized块，由于instance此时不是null,因此它马上离开了synchronized块并将结果返回给调用该方法的程序</li>
<li>此时B线程打算使用Singleton实例，却发现它没有被初始化，于是错误发生了</li>
</ol>
<h1>结构型模式： 把类或对象结合在一起形成一个更大的结构</h1>
<h2>适配器模式</h2>
<h3>接口适配器</h3>
<p>接口适配器主要作用就是，接口定义方法太多，底下实现并不需要那么多的实现。</p>
<p>例如： 现在有一家很大的公司生产汽车，自行车，摩托车等。这家公司想在某个地方开家新厂，这家公司发现，当地都很有钱，只开车。于是这家公司在这当地开了家汽车制造厂</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//这家公司</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Comany</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">produceCar</span><span class="params">()</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">produceMotocycle</span><span class="params">()</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">produceBicycle</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">ComanyAdapter</span> <span class="keyword">implements</span> <span class="title">Comany</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">produceCar</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="comment">//我有能力去做，但看我愿不愿意去做</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">produceMotocycle</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="comment">//我有能力去做，但看我愿不愿意去做</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">produceBicycle</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="comment">//我有能力去做，但看我愿不愿意去做</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//开汽车厂了</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">CarFactory</span> <span class="keyword">extends</span> <span class="title">ComanyAdapter</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">produceCar</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"生产汽车"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行……</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String []args)</span></span>&#123;</span><br><span class="line">        ComanyAdapter comanyAdapter=<span class="keyword">new</span> CarFactory();</span><br><span class="line">        <span class="comment">//生产汽车</span></span><br><span class="line">        comanyAdapter.produceCar();</span><br><span class="line">        <span class="comment">//生产不了</span></span><br><span class="line">        comanyAdapter.produceMotocycle();</span><br><span class="line">        <span class="comment">//生产不了</span></span><br><span class="line">        comanyAdapter.produceBicycle();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>接口适配器还常常用在插件结构设计，框架结构设计。先预先定义好结构方法，由下面去实现发法，这样实现就很灵活。</p>
<hr>
<h3>类适配器</h3>
<p>类适配器主要用于扩展旧的功能</p>
<p>例如： 现在有一家很小的公司生产自行车。这家公司想在某个地方开家新厂，这家公司发现，当地都开摩托车和自行车。于是这家公司在这当地申请贷款开了家摩托车制造厂</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//这家公司</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Comany</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">produceBicycle</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"生产自行车"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//申请贷款</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Loans</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">produceMotocycle</span><span class="params">()</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">produceBicycle</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//申请贷款了之后公司变的有规模了</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MiddleComany</span> <span class="keyword">extends</span> <span class="title">Comany</span> <span class="keyword">implements</span> <span class="title">Loans</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> Comany comany;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">MiddleComany</span><span class="params">(Comany comany)</span></span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.comany=comany;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">produceMotocycle</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.prinln(<span class="string">"生产摩托车"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">produceBicycle</span><span class="params">()</span></span>&#123;</span><br><span class="line">        comany.produceBicycle();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行……</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String []args)</span></span>&#123;</span><br><span class="line">        Comany comany=<span class="keyword">new</span> Comany();</span><br><span class="line">        comany.produceBicycle();</span><br><span class="line">        <span class="comment">//扩展规模</span></span><br><span class="line">        MiddleComany middleComany=<span class="keyword">new</span> MiddleComany(comany);</span><br><span class="line">        middleComany.produceBicycle();</span><br><span class="line">        middleComany.produceMotocycle();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>类适配很好更之前的功能结合在一起，很容易对旧功能进行升级改造</p>
<hr>
<h3>对象适配器</h3>
<p>跟类适配器差不多，但是没有类适配器灵活，也是主要用于扩展旧的功能</p>
<p>例如： 现在有一家很小的公司生产自行车。这家公司想在某个地方开家新厂，这家公司发现，当地都开摩托车和自行车。这家公司之前赚够了钱，有能力自行升级</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//这家公司</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Comany</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">produceBicycle</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"生产自行车"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//申请贷款了之后公司变的有规模了</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MiddleComany</span> <span class="keyword">extends</span> <span class="title">Comany</span></span>&#123;</span><br><span class="line">    <span class="keyword">private</span> Comany comany;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">MiddleComany</span><span class="params">(Comany comany)</span></span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.comany=comany;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">produceMotocycle</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.prinln(<span class="string">"生产摩托车"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">produceBicycle</span><span class="params">()</span></span>&#123;</span><br><span class="line">        comany.produceBicycle();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行……</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String []args)</span></span>&#123;</span><br><span class="line">        Comany comany=<span class="keyword">new</span> Comany();</span><br><span class="line">        comany.produceBicycle();</span><br><span class="line">        <span class="comment">//扩展规模</span></span><br><span class="line">        MiddleComany middleComany=<span class="keyword">new</span> MiddleComany(comany);</span><br><span class="line">        middleComany.produceBicycle();</span><br><span class="line">        middleComany.produceMotocycle();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>以上三种适配器模式都很好扩展了旧的功能，但它们的灵活性是依次降低的，即接口适配器》类适配器》对象适配器</p>
<h2>桥接模式</h2>
<p>桥接是用于把抽象化与实现化解耦，使得二者可以独立变化。这种类型的设计模式属于结构型模式，它通过提供抽象化和实现化之间的桥接结构，来实现二者的解耦。</p>
<p>这种模式涉及到一个作为桥接的接口，使得实体类的功能独立于接口实现类。这两种类型的类可被结构化改变而互不影响。</p>
<p>大多数讲桥接模式都讲的术语话，这里用通俗易懂的话来讲述。</p>
<p><strong>假如一支笔，有不同的颜色，有不同的牌子，不同牌子代表不同厂家生产，代码表示如下</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Color</span> </span>&#123;</span><br><span class="line">    <span class="function">String <span class="title">drawColor</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Red</span> </span>&#123;</span><br><span class="line">    <span class="function">String <span class="title">drawColor</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">"Red"</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Yellow</span> </span>&#123;</span><br><span class="line">    <span class="function">String <span class="title">drawColor</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">"Yellow"</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Blue</span> </span>&#123;</span><br><span class="line">    <span class="function">String <span class="title">drawColor</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">"Blue"</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//生产笔</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">ProducePan</span></span>&#123;</span><br><span class="line">    <span class="keyword">private</span> Color color;</span><br><span class="line">    Bridge(Color color) &#123;</span><br><span class="line">        <span class="keyword">this</span>.color = color;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function">Color <span class="title">getColor</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> color;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">setSource</span><span class="params">(Color color)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.color = color;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title">produce</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3>一对多桥接</h3>
<p>现在有个叫晨光的牌子的公司去生成红，黄，蓝三种颜色的笔。那么晨光这个公司不可能去造三个厂分别去生成这个笔，这不现实，而且代价有点大。现实的做法是一个厂一台机器换三种不同颜色的原料即可。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">//晨光</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ChenGuang</span> <span class="keyword">extends</span> <span class="title">ProducePan</span> </span>&#123;</span><br><span class="line">    ChenGuang(Color color) &#123;</span><br><span class="line">        <span class="keyword">super</span>(color);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">produce</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"生产晨光的笔"</span>);</span><br><span class="line">        System.out.println(color.drawColor());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行……</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//晨光生产的笔</span></span><br><span class="line">        ProducePan producePan=<span class="keyword">new</span> ChenGuang(<span class="keyword">new</span> Red());</span><br><span class="line">        producePan.produce();</span><br><span class="line">        ProducePan.setSource(<span class="keyword">new</span> Blue());</span><br><span class="line">        producePan.produce();</span><br><span class="line">        ProducePan.setSource(<span class="keyword">new</span> Yellow());</span><br><span class="line">        producePan.produce();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3>多对多桥接</h3>
<p>现在又来了几家公司各晨光抢生意，这几家公司叫A, B杂牌</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">//A</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">A</span> <span class="keyword">extends</span> <span class="title">ProducePan</span> </span>&#123;</span><br><span class="line">    ChenGuang(Color color) &#123;</span><br><span class="line">        <span class="keyword">super</span>(color);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">produce</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"生产A的笔"</span>);</span><br><span class="line">        System.out.println(color.drawColor());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//B</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">B</span> <span class="keyword">extends</span> <span class="title">ProducePan</span> </span>&#123;</span><br><span class="line">    ChenGuang(Color color) &#123;</span><br><span class="line">        <span class="keyword">super</span>(color);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">produce</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"生产B的笔"</span>);</span><br><span class="line">        System.out.println(color.drawColor());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行……</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//晨光生产的笔</span></span><br><span class="line">        ProducePan producePan=<span class="keyword">new</span> ChenGuang(<span class="keyword">new</span> Red());</span><br><span class="line">        producePan.produce();</span><br><span class="line">        ProducePan.setSource(<span class="keyword">new</span> Blue());</span><br><span class="line">        producePan.produce();</span><br><span class="line">        ProducePan.setSource(<span class="keyword">new</span> Yellow());</span><br><span class="line">        producePan.produce();</span><br><span class="line">        <span class="comment">//A生产的笔</span></span><br><span class="line">        producePan=<span class="keyword">new</span> A(<span class="keyword">new</span> Red());</span><br><span class="line">        producePan.produce();</span><br><span class="line">        ProducePan.setSource(<span class="keyword">new</span> Blue());</span><br><span class="line">        producePan.produce();</span><br><span class="line">        ProducePan.setSource(<span class="keyword">new</span> Yellow());</span><br><span class="line">        producePan.produce();</span><br><span class="line">        <span class="comment">//B生产的笔</span></span><br><span class="line">        producePan=<span class="keyword">new</span> B(<span class="keyword">new</span> Red());</span><br><span class="line">        producePan.produce();</span><br><span class="line">        ProducePan.setSource(<span class="keyword">new</span> Blue());</span><br><span class="line">        producePan.produce();</span><br><span class="line">        ProducePan.setSource(<span class="keyword">new</span> Yellow());</span><br><span class="line">        producePan.produce();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>桥接模式是一种很实用的结构型设计模式，如果软件系统中某个类存在两个独立变化的维度，通过该模式可以将这两个维度分离出来，使两者可以独立扩展，让系统更加符合&quot;单一职责原则”。与多层继承方案不同，它将两个独立变化的维度设计为两个独立的继承等级结构，并且在抽象层建立一个抽象关联，该关联关系类似一条连接两个独立继承结构的桥，故名桥接模式。</p>
<p>桥接模式（Bridge Pattern)： 将抽象部分与它的实现部分分离，使它们都可以独立地变化。它是一种对象结构型模式，又称为柄体（Handle and Body) 模式或接口（Interface) 模式。</p>
<h2>组合模式</h2>
<ol>
<li>组合模式，就是在一个对象中包含其他对象，这些被包含的对象可能是终点对象（不再包含别的对象），也有可能是非终点对象（其内部还包含其他对象，或叫组对象），我们将对象称为节点，即一个根节点包含许多子节点，这些子节点有的不再包含子节点，而有的仍然包含子节点，以此类推。</li>
<li>所谓组合模式，其实说的是对象包含对象的问题，通过组合的方式（在对象内部引用对象）来进行布局，我认为这种组合是区别于继承的，而另一层含义是指树形结构子节点的抽象（将叶子节点与数枝节点抽象为子节点），区别于普通的分别定义叶子节点与数枝节点的方式。</li>
</ol>
<p>说白了，组合模式就是一个类似树的集合，我们通过下面的实例来演示组合模式的用法。实例演示了一个组织中员工的层次结构。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Employee</span> </span>&#123;</span><br><span class="line">   <span class="keyword">private</span> String name;</span><br><span class="line">   <span class="keyword">private</span> String dept;</span><br><span class="line">   <span class="keyword">private</span> <span class="keyword">int</span> salary;</span><br><span class="line">   <span class="keyword">private</span> List&lt;Employee&gt; subordinates;</span><br><span class="line"></span><br><span class="line">   <span class="comment">//构造函数</span></span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="title">Employee</span><span class="params">(String name, String dept, <span class="keyword">int</span> sal)</span> </span>&#123;</span><br><span class="line">      <span class="keyword">this</span>.name = name;</span><br><span class="line">      <span class="keyword">this</span>.dept = dept;</span><br><span class="line">      <span class="keyword">this</span>.salary = sal;</span><br><span class="line">      subordinates = <span class="keyword">new</span> ArrayList&lt;Employee&gt;();</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">add</span><span class="params">(Employee e)</span> </span>&#123;</span><br><span class="line">      subordinates.add(e);</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">remove</span><span class="params">(Employee e)</span> </span>&#123;</span><br><span class="line">      subordinates.remove(e);</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="function"><span class="keyword">public</span> List&lt;Employee&gt; <span class="title">getSubordinates</span><span class="params">()</span></span>&#123;</span><br><span class="line">     <span class="keyword">return</span> subordinates;</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="function"><span class="keyword">public</span> String <span class="title">toString</span><span class="params">()</span></span>&#123;</span><br><span class="line">      <span class="keyword">return</span> (<span class="string">"Employee :[ Name : "</span>+ name</span><br><span class="line">      +<span class="string">", dept : "</span>+ dept + <span class="string">", salary :"</span></span><br><span class="line">      + salary+<span class="string">" ]"</span>);</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行……</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">      Employee CEO = <span class="keyword">new</span> Employee(<span class="string">"John"</span>, <span class="string">"CEO"</span>, <span class="number">30000</span>);</span><br><span class="line"></span><br><span class="line">      Employee headSales = <span class="keyword">new</span> Employee(<span class="string">"Robert"</span>, <span class="string">"Head Sales"</span>, <span class="number">20000</span>);</span><br><span class="line"></span><br><span class="line">      Employee headMarketing = <span class="keyword">new</span> Employee(<span class="string">"Michel"</span>, <span class="string">"Head Marketing"</span>, <span class="number">20000</span>);</span><br><span class="line"></span><br><span class="line">      Employee clerk1 = <span class="keyword">new</span> Employee(<span class="string">"Laura"</span>, <span class="string">"Marketing"</span>, <span class="number">10000</span>);</span><br><span class="line">      Employee clerk2 = <span class="keyword">new</span> Employee(<span class="string">"Bob"</span>, <span class="string">"Marketing"</span>, <span class="number">10000</span>);</span><br><span class="line"></span><br><span class="line">      Employee salesExecutive1 = <span class="keyword">new</span> Employee(<span class="string">"Richard"</span>, <span class="string">"Sales"</span>, <span class="number">10000</span>);</span><br><span class="line">      Employee salesExecutive2 = <span class="keyword">new</span> Employee(<span class="string">"Rob"</span>, <span class="string">"Sales"</span>, <span class="number">10000</span>);</span><br><span class="line"></span><br><span class="line">      CEO.add(headSales);</span><br><span class="line">      CEO.add(headMarketing);</span><br><span class="line"></span><br><span class="line">      headSales.add(salesExecutive1);</span><br><span class="line">      headSales.add(salesExecutive2);</span><br><span class="line"></span><br><span class="line">      headMarketing.add(clerk1);</span><br><span class="line">      headMarketing.add(clerk2);</span><br><span class="line"></span><br><span class="line">      <span class="comment">//打印该组织的所有员工</span></span><br><span class="line">      System.out.println(CEO);</span><br><span class="line">      <span class="keyword">for</span> (Employee headEmployee : CEO.getSubordinates()) &#123;</span><br><span class="line">         System.out.println(headEmployee);</span><br><span class="line">         <span class="keyword">for</span> (Employee employee : headEmployee.getSubordinates()) &#123;</span><br><span class="line">            System.out.println(employee);</span><br><span class="line">         &#125;</span><br><span class="line">      &#125;</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2>装饰器模式</h2>
<p>顾名思义在原来基础上锦上添花</p>
<p>涉及角色</p>
<ol>
<li>抽象组件： 定义一个抽象接口，来规范准备附加功能的类</li>
<li>具体组件： 将要被附加功能的类，实现抽象构件角色接口</li>
<li>抽象装饰者： 持有对具体构件角色的引用并定义与抽象构件角色一致的接口</li>
<li>具体装饰： 实现抽象装饰者角色，负责对具体构件添加额外功能</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Person</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">eat</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Man</span> <span class="keyword">implements</span> <span class="title">Person</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">eat</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"男人在吃"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">Decorator</span> <span class="keyword">implements</span> <span class="title">Person</span> </span>&#123;</span><br><span class="line">    <span class="keyword">protected</span> Person person;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setPerson</span><span class="params">(Person person)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.person = person;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">eat</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        person.eat();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ManDecoratorA</span> <span class="keyword">extends</span> <span class="title">Decorator</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">eat</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.eat();</span><br><span class="line">        reEat();</span><br><span class="line">        System.out.println(<span class="string">"ManDecoratorA类"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">reEat</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"再吃一顿饭"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ManDecoratorB</span> <span class="keyword">extends</span> <span class="title">Decorator</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">eat</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.eat();</span><br><span class="line">        System.out.println(<span class="string">"==============="</span>);</span><br><span class="line">        System.out.println(<span class="string">"ManDecoratorB类"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行……</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Man man = <span class="keyword">new</span> Man();</span><br><span class="line">        ManDecoratorA md1 = <span class="keyword">new</span> ManDecoratorA();</span><br><span class="line">        ManDecoratorB md2 = <span class="keyword">new</span> ManDecoratorB();</span><br><span class="line"></span><br><span class="line">        md1.setPerson(man);</span><br><span class="line">        md2.setPerson(md1);</span><br><span class="line">        md2.eat();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2>外观模式</h2>
<p>外观模式（Facade),他隐藏了系统的复杂性，并向客户端提供了一个可以访问系统的接口。这种类型的设计模式属于结构性模式。为子系统中的一组接口提供了一个统一的访问接口，这个接口使得子系统更容易被访问或者使用。</p>
<p>例如： 一台电脑里有CPU， 内存， 显卡， 主板，当电脑启动时，这些都得启动，当电脑关闭时，也必须都关闭</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> interface <span class="title">Action</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">startup</span><span class="params">()</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">shutdown</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">CPU</span> <span class="keyword">implements</span> <span class="title">Action</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">startup</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"cpu startup!"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">shutdown</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"cpu shutdown!"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Memory</span> <span class="keyword">implements</span> <span class="title">Action</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">startup</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"memory startup!"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">shutdown</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"memory shutdown!"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Graphics</span> <span class="keyword">implements</span> <span class="title">Action</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">startup</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"graphics startup!"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">shutdown</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"graphics shutdown!"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MainBoard</span> <span class="keyword">implements</span> <span class="title">Action</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">startup</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"mainBoard startup!"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">shutdown</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"mainBoard shutdown!"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Computer</span> <span class="keyword">implements</span> <span class="title">Action</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> CPU cpu;</span><br><span class="line">    <span class="keyword">private</span> Memory memory;</span><br><span class="line">    <span class="keyword">private</span> Graphics graphics;</span><br><span class="line">    <span class="keyword">private</span> MainBoard mainBoard;</span><br><span class="line">    Computer() &#123;</span><br><span class="line">        cpu = <span class="keyword">new</span> CPU();</span><br><span class="line">        memory = <span class="keyword">new</span> Memory();</span><br><span class="line">        graphics = <span class="keyword">new</span> Graphics();</span><br><span class="line">        mainBoard = <span class="keyword">new</span> MainBoard();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">startup</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"start the computer!"</span>);</span><br><span class="line">        mainBoard.startup();</span><br><span class="line">        cpu.startup();</span><br><span class="line">        memory.startup();</span><br><span class="line">        graphics.startup();</span><br><span class="line">        System.out.println(<span class="string">"start computer finished!"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">shutdown</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"begin to close the computer!"</span>);</span><br><span class="line">        mainBoard.shutdown();</span><br><span class="line">        cpu.shutdown();</span><br><span class="line">        memory.shutdown();</span><br><span class="line">        graphics.shutdown();</span><br><span class="line">        System.out.println(<span class="string">"computer closed!"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行……</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Computer computer = <span class="keyword">new</span> Computer();</span><br><span class="line">        computer.startup();</span><br><span class="line">        computer.shutdown();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>上述的模式，将电脑里面所有硬件对外进行隐藏，不需要一个个单独启用，而是对外提供统一的方法。这样既影藏了细节，还对实现方法解耦，即使以后升级修改，不会对外部造成影响。</p>
<h2>享元模式</h2>
<p>享元的目的是为了减少不会要额内存消耗，将多个对同一对象的访问集中起来，不必为每个访问者创建一个单独的对象，以此来降低内存的消耗。就好像线程池，数据库的连接池一样。它们的操作是昂贵的，且我们需要经常使用它，因此我们不必每次都创建它们，而是把它们一次性创建好，当需要的时候，从里面取出，不用时再放回去即可。</p>
<p>例如： 幼儿园的小朋友要画油画，但是小朋友又没有笔，只有老师带了10笔，所以小朋友只有找老师要，但最多只有10个小朋友同时获得笔，小朋友用完之后就得放回去</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Pen</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">draw</span><span class="params">(String context)</span></span>&#123;</span><br><span class="line">        System.out.println(context)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">PenPool</span> </span>&#123;</span><br><span class="line">    <span class="function">Pen <span class="title">gain</span><span class="params">()</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">putBack</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Teacher</span> <span class="keyword">implements</span> <span class="title">PenPool</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> capacity;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> point;</span><br><span class="line">    <span class="keyword">private</span> Pen[] pens;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Teacher</span><span class="params">(<span class="keyword">int</span> capacity)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.capacity = capacity;</span><br><span class="line">        <span class="keyword">this</span>.point = <span class="number">0</span>;</span><br><span class="line">        pens = <span class="keyword">new</span> Pen[<span class="keyword">this</span>.capacity];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> Pen <span class="title">gain</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">this</span>.point + <span class="number">1</span> &gt;= <span class="keyword">this</span>.capacity) <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">        Pen temp = pens[<span class="keyword">this</span>.point];</span><br><span class="line">        <span class="keyword">if</span> (temp == <span class="keyword">null</span>) &#123;</span><br><span class="line">            temp = <span class="keyword">new</span> Pen();</span><br><span class="line">            pens[<span class="keyword">this</span>.point] = temp;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">this</span>.point++;</span><br><span class="line">        <span class="keyword">return</span> temp;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">putBack</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">this</span>.point &gt; <span class="number">0</span>) <span class="keyword">this</span>.point--;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行……</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        PenPool pool = <span class="keyword">new</span> Teacher(<span class="number">10</span>);</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= <span class="number">100</span>; i++) &#123;</span><br><span class="line">            Pen pen = pool.gain();</span><br><span class="line">            <span class="keyword">if</span> (pen == <span class="keyword">null</span>) System.out.println(<span class="string">"老师这没有笔了，等其它同学用完！ "</span>)</span><br><span class="line">            pen.draw(<span class="string">"第"</span> + i + <span class="string">"取笔"</span>);</span><br><span class="line">            <span class="keyword">if</span> (i % <span class="number">4</span> == <span class="number">0</span>) pool.putBack();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2>代理模式</h2>
<p><strong>我们首先先来搞明白什么是代理</strong>，我们生活中，经常会听到代理这个词，就比如</p>
<ol>
<li>炒股，别人代理帮你炒，但是最终受益和决定权都在你的手里</li>
<li>秘书，一个大企业的老总，不可能每件事都自己做，有些事有人会代理你去做，就是要给工资</li>
<li>明星，明星要处理某些事情不方便就会请人代理去做</li>
</ol>
<p><strong>代理其实就是处理一些必要但又不是特别重要的事情</strong></p>
<h3>普通代理</h3>
<p>普通代理就是以应编码的方式将需要处理的事，编写到目标去</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Sourceable</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">method</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Source</span> <span class="keyword">implements</span> <span class="title">Sourceable</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">method</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"原方法"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SourceProxy</span> <span class="keyword">implements</span> <span class="title">Sourceable</span></span>&#123;</span><br><span class="line">    <span class="keyword">private</span> Sourceable origin;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">SourceProxy</span><span class="params">(Sourceable sourceable)</span></span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.origin=sourceable;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">method</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"原方法之前处理一些事"</span>);</span><br><span class="line">        origin.method();</span><br><span class="line">        System.out.println(<span class="string">"原方法之后处理一些事"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行……</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestStaticProxy</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Sourceable source = <span class="keyword">new</span> Source();</span><br><span class="line">        Sourceable proxy = <span class="keyword">new</span> SourceProxy(source);</span><br><span class="line">        source.method();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>运行结果</strong></p>
<blockquote>
<p>原方法之前处理一些事</p>
<p>原方法</p>
<p>原方法之后处理一些事</p>
</blockquote>
<h3>动态代理</h3>
<p>动态代理就是在运行期间将需要处理的事，编写到目标中去</p>
<p><strong>java动态代理的用到的类</strong></p>
<ul>
<li>java.lang.reflect. InvocationHandler: 调用处理器接口，自定义invokle方法，用于实现对于委托类的代理访问</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> 该方法负责集中处理动态代理类上的所有方法调用。</span></span><br><span class="line"><span class="comment"> 第一个参数既是代理类实例，</span></span><br><span class="line"><span class="comment"> 第二个参数是被调用的方法对象</span></span><br><span class="line"><span class="comment"> 第三个方法是调用参数。</span></span><br><span class="line"><span class="comment"> 调用处理器根据这三个参数进行预处理或分派到委托类实例上发射执行</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> Object <span class="title">invoke</span><span class="params">(Object proxy, Method method, Object[] args)</span> <span class="keyword">throws</span> Throwable</span>;</span><br></pre></td></tr></table></figure>
<ul>
<li>java.lang.reflect. Proxy: 动态代理机制的主类，提供一组静态方法为一组接口动态的生成对象和代理类</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 方法1: 该方法用于获取指定代理对象所关联的调用处理器</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> InvocationHandler <span class="title">getInvocationHandler</span><span class="params">(Object proxy)</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function"><span class="comment">// 方法2： 该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象</span></span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Class&lt;?&gt; <span class="title">getProxyClass</span><span class="params">(ClassLoader loader, Class&lt;?&gt;... interfaces)</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function"><span class="comment">// 方法3： 该方法用于判断指定类对象是否是一个动态代理类</span></span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">boolean</span> <span class="title">isProxyClass</span><span class="params">(Class&lt;?&gt; cl)</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function"><span class="comment">// 方法4： 该方法用于为指定类装载器， 一组接口及调用处理器生成动态代理类实例</span></span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Object <span class="title">newProxyInstance</span><span class="params">(ClassLoader loader, Class&lt;?&gt;[] interfaces, InvocationHandler h)</span></span></span><br></pre></td></tr></table></figure>
<ul>
<li>java.lang. ClassLoader: 类装载器类，将类的字节码装载到Java虚拟机（JVM) 中并为其定义类对象，然后该类才能被使用</li>
</ul>
<p><strong><em>区别</em></strong></p>
<p><strong>Proxy类与普通类的唯一区别就是其字节码是由JVM在运行时动态生成的而非预存在于任何一个 .class文件中</strong>，每次生成动态代理类对象时都需要指定一个类装载器对象，就是newProxyInstance方法第一个参数</p>
<p><strong>java动态代理创建对象的过程为如下步骤</strong></p>
<ol>
<li>定义InterceptorAspect切面接口</li>
<li>实现InvocationHandler处理器接口</li>
<li>用newProxyInstance获取代理对象，但这个时候需要把这个InvocationHandler实例类传进第三个参数，为了方便，所以我们将获取代理对象的方法也放在这个类中就是下面的bind方法</li>
<li>实现InterceptorAspect切面接口，这里方法是要绑定到代理对象里面的</li>
<li>将切面和对象绑定在一起生成代理对象</li>
</ol>
<p><strong>来个传统的jdbc操作吧，看看用动态代理是怎么做的</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">InterceptorAspect</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">before</span><span class="params">(Object obj)</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">after</span><span class="params">(Object obj)</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">afterReturning</span><span class="params">(Object obj)</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">afterThrowing</span><span class="params">(Object obj)</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DatabaseProxy</span> <span class="keyword">implements</span> <span class="title">InvocationHandler</span> </span>&#123;</span><br><span class="line">    <span class="comment">//保存原对象</span></span><br><span class="line">    Object originObj;</span><br><span class="line">    <span class="comment">//保存切面对象</span></span><br><span class="line">    InterceptorAspect aspect</span><br><span class="line">    <span class="comment">//返回代理对象</span></span><br><span class="line">    <span class="keyword">public</span> &lt;T&gt; <span class="function">T <span class="title">bind</span><span class="params">(T obj, InterceptorAspect aspect)</span> </span>&#123;</span><br><span class="line">        originObj = obj;</span><br><span class="line">        <span class="keyword">this</span>.aspect=aspect;</span><br><span class="line">        <span class="comment">//获取Class</span></span><br><span class="line">        Class c = obj.getClass();</span><br><span class="line">        <span class="keyword">return</span> (T) Proxy.newProxyInstance(c.getClassLoader(), c.getInterfaces(), <span class="keyword">this</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//代理对象所执行的函数</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Object <span class="title">invoke</span><span class="params">(Object proxy, Method method, Object[] args)</span> <span class="keyword">throws</span> Throwable </span>&#123;</span><br><span class="line">        <span class="keyword">boolean</span> isException = <span class="keyword">false</span>; <span class="comment">//是否有异常</span></span><br><span class="line">        Object retObj = <span class="keyword">null</span>; <span class="comment">//委托类方法的返回值</span></span><br><span class="line">        aspect.before(originObj); <span class="comment">//调用方法前可以做一些事情</span></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            retObj = method.invoke(originObj, args); <span class="comment">//调用委托类的方法</span></span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            isException = <span class="keyword">true</span>;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">            <span class="keyword">if</span> (isException) aspect.afterReturning(originObj); <span class="comment">//无异常可以做一些事情</span></span><br><span class="line">            <span class="keyword">else</span> aspect.afterThrowing(originObj); <span class="comment">//有异常可以做一些事情</span></span><br><span class="line">            aspect.after(originObj); <span class="comment">//调用方法后可以做一些事情</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> retObj;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DatabaseUtils</span> </span>&#123;</span><br><span class="line">	<span class="comment">//ThreadLocal多线程共享变量管理器，在高并发需要这个操作</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> ThreadLocal&lt;Connection&gt; threadLocal = <span class="keyword">new</span> ThreadLocal&lt;Connection&gt;();</span><br><span class="line">    <span class="comment">//jdbc固定操作切面</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> JdbcAspect aspect=<span class="keyword">new</span> JdbcAspect();</span><br><span class="line">    <span class="comment">//将切面和对象绑定到一起，产生一个代理对象</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> &lt;T&gt; <span class="function">T <span class="title">Bind</span><span class="params">(T obj)</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> DatabaseProxy().bind(obj, aspect);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Statement <span class="title">getStatement</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        Connection con = threadLocal.get();</span><br><span class="line">        <span class="keyword">if</span>(con==<span class="keyword">null</span>) <span class="keyword">throw</span> <span class="keyword">new</span> Exception(<span class="string">"请先获得代理对象"</span>);</span><br><span class="line">        <span class="keyword">return</span> con.createStatement();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//实现InterceptorAspect接口，jdbc固定操作切面</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">JdbcAspect</span> <span class="keyword">implements</span> <span class="title">InterceptorAspect</span> </span>&#123;</span><br><span class="line">        <span class="comment">//获取连接</span></span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">before</span><span class="params">(Object obj)</span> </span>&#123;</span><br><span class="line">            Connection con = threadLocal.get();</span><br><span class="line">            <span class="keyword">if</span> (con != <span class="keyword">null</span>) <span class="keyword">return</span>;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                Class.forName(<span class="string">"com.mysql.jdbc. Driver"</span>);</span><br><span class="line">                String url = <span class="string">"jdbc:mysql://localhost:3306/test"</span>;</span><br><span class="line">                String username = <span class="string">"root"</span>;</span><br><span class="line">                String password = <span class="string">"root"</span>;</span><br><span class="line">                con = DriverManager.getConnection(url, username, password);</span><br><span class="line">                threadLocal.set(con);</span><br><span class="line">            &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//关闭连接</span></span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">after</span><span class="params">(Object obj)</span> </span>&#123;</span><br><span class="line">            Connection con = threadLocal.get();</span><br><span class="line"></span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="keyword">if</span> (con != <span class="keyword">null</span>) con.close();</span><br><span class="line">            &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//提交</span></span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">afterReturning</span><span class="params">(Object obj)</span> </span>&#123;</span><br><span class="line">            Connection con = threadLocal.get();</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="keyword">if</span> (con != <span class="keyword">null</span>) con.commit();</span><br><span class="line">            &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//回滚</span></span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">afterThrowing</span><span class="params">(Object obj)</span> </span>&#123;</span><br><span class="line">            Connection con = threadLocal.get();</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="keyword">if</span> (con != <span class="keyword">null</span>) con.rollback();</span><br><span class="line">            &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Dao</span></span>&#123;</span><br><span class="line">	<span class="keyword">public</span> String[] getAllString();</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DaoImpl</span></span>&#123;</span><br><span class="line">	<span class="comment">//现在里面现在根本就没有那些繁杂的数据连接关闭等操作，清晰了不少呢</span></span><br><span class="line">	<span class="keyword">public</span> String[] getAllString()&#123;</span><br><span class="line">		<span class="comment">//获得Statement</span></span><br><span class="line">		Statement sta=DatabaseUtils.getStatement();</span><br><span class="line">		<span class="comment">//······一系列数据库操作</span></span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行……</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestDynamicProxy</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">    	<span class="comment">//看好怎么用的</span></span><br><span class="line">    	<span class="comment">//获得Dao层代理对象，这里一定要用接口来接</span></span><br><span class="line">        Dao dao=DatabaseUtils.bind(<span class="keyword">new</span> DaoImpl);</span><br><span class="line">        <span class="comment">//使用</span></span><br><span class="line">        String []str=dao.getAllString();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>大家会决定很麻烦，那是因为项目小不觉的什么，一但大项目要写成千个这种操作，写个这个岂不是美哉，向MyBaits, Spring的AOP里面就经常出现动态代理。</p>
<h1>行为型模式： 类和对象如何交互，及划分责任和算法</h1>
<h2>责任链模式</h2>
<p>责任链模式通俗来说就是关联一串能够处理事务的对象，使多个对象都有机会处理请求，从而避免了请求的发送者和接收者之间的耦合关系。将这些对象连成一条链，并沿着这条链传递该请求，直到有对象处理它为止。</p>
<p>例如： 我们要显示一串字符串，但是有些东西不让显示，一次需要对字符串经过几次处理。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">StringHandle</span> </span>&#123;</span><br><span class="line">    <span class="function">String <span class="title">dealString</span><span class="params">(String string)</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">StringHandleChain</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">addFilter</span><span class="params">(StringHandle stringHandle)</span></span>;</span><br><span class="line">    <span class="function">List&lt;StringHandle&gt; <span class="title">getChain</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">StringHandleChainImpl</span> <span class="keyword">implements</span> <span class="title">StringHandleChain</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> List&lt;StringHandle&gt; list;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">StringHandleChainImpl</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        list=<span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">addFilter</span><span class="params">(StringHandle stringHandle)</span></span>&#123;</span><br><span class="line">        list.add(stringHandle);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function">List&lt;StringHandle&gt; <span class="title">getChain</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> list;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Display</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> StringHandleChain stringHandleChain;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Display</span><span class="params">(StringHandleChain stringHandleChain)</span></span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.stringHandleChain=stringHandleChain;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">show</span><span class="params">(String string)</span></span>&#123;</span><br><span class="line">        List&lt;StringHandle&gt; list=stringHandleChain.getChain();</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>; i&lt;list.length(); i++)&#123;</span><br><span class="line">            string=list.get(i).dealString(string);</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(string);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//将&lt;换成[，将&gt;换成]</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Replase</span> <span class="keyword">implements</span> <span class="title">StringHandle</span> </span>&#123;</span><br><span class="line">    <span class="function">String <span class="title">dealString</span><span class="params">(String string)</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> string.replase(<span class="string">"&lt;"</span>, <span class="string">"["</span>).replase(<span class="string">"&gt;"</span>, <span class="string">"]"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//删除空格</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Delete</span> <span class="keyword">implements</span> <span class="title">StringHandle</span> </span>&#123;</span><br><span class="line">    <span class="function">String <span class="title">dealString</span><span class="params">(String string)</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> string.replase(<span class="string">" "</span>, <span class="string">""</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行……</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span></span>&#123;</span><br><span class="line">        StringHandleChain stringHandleChain = <span class="keyword">new</span> StringHandleChainImpl();</span><br><span class="line">        stringHandleChain.addFilter(<span class="keyword">new</span> Replase());</span><br><span class="line">        stringHandleChain.addFilter(<span class="keyword">new</span> Delete());</span><br><span class="line">        Display display=<span class="keyword">new</span> Display(stringHandleChain);</span><br><span class="line">        dispaly.show(<span class="string">"&lt;p&gt; 你好吗！ &lt;/p&gt;"</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这里举了个简单的例子，方便理解。责任链跟AOP面向切面编程的理念是一样，将处理的细节分层，在一层层中逐步解决。责任链有很多不同的实现，其理念都是一样。比如运用动态代理也可以实现动态代理。还有别的就是一个对象中保存一个另一个属于同一个类的对象，这要有点像链表，就像下面这样。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Hand</span></span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">int</span> count=<span class="number">0</span>;</span><br><span class="line">    <span class="keyword">private</span> Hand other;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setOther</span><span class="params">(Hand other)</span></span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.other=other;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">do</span><span class="params">()</span></span>&#123;</span><br><span class="line">        other.<span class="keyword">do</span>();</span><br><span class="line">        count++;</span><br><span class="line">        System.out.println(<span class="string">"第几只手"</span>+count);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span></span>&#123;</span><br><span class="line">        Hand one=<span class="keyword">new</span> Hand(), two=<span class="keyword">new</span> Hand(), three=<span class="keyword">new</span> Hand();</span><br><span class="line">        one.setOther(two);</span><br><span class="line">        two.setOther(three);</span><br><span class="line">        one.<span class="keyword">do</span>();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2>命令模式</h2>
<p>命令模式（Command Pattern) 是一种数据驱动的设计模式，它属于行为型模式。请求以命令的形式包裹在对象中，并传给调用对象。调用对象寻找可以处理该命令的合适的对象，并把该命令传给相应的对象，该对象执行命令。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//第一步： 定义Command,声明执行操作的接口</span></span><br><span class="line"><span class="comment">//命令接口</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Command</span> </span>&#123;</span><br><span class="line">    <span class="comment">//执行操作</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">excute</span><span class="params">()</span></span>;</span><br><span class="line">    <span class="comment">//撤销操作</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">unDo</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//第二步： 定义ConcreteCommand,将一个接收者对象绑定于一个动作。</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ConcreteCommand</span> <span class="keyword">implements</span> <span class="title">Command</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 持有一个接受者Receiver的引用，绑定一个特定的操作</span></span><br><span class="line">    Receiver receiver;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">ConcreteCommand</span><span class="params">(Receiver receiver)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.receiver = receiver;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">excute</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 接受者绑定执行动作</span></span><br><span class="line">        receiver.action();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">unDo</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 接受者绑定的撤销动作</span></span><br><span class="line">        receiver.unAction();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//第三步： 定义Receiver,知道如何实现与执行一个请求相关的操作</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Receiver</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">action</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"执行一个命令"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">unAction</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"撤销一个命令"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//第四步： 定义Invoker,要求该命令执行这个请求。</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Invoker</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 调用者持有一个命令对象</span></span><br><span class="line">    Command command;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> Command <span class="title">getCommand</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> command;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setCommand</span><span class="params">(Command command)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.command = command;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 执行命令</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">excuteCommmand</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        command.excute();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 撤销命令</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">undoCommand</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        command.unDo();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行……</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 创建命令的接受者</span></span><br><span class="line">        Receiver receiver = <span class="keyword">new</span> Receiver();</span><br><span class="line">        <span class="comment">// 创建命令对象，并设定它的接受者</span></span><br><span class="line">        Command command = <span class="keyword">new</span> ConcreteCommand(receiver);</span><br><span class="line">        <span class="comment">// 创建命令执行者，并将相应的命令作为参数传递给Invoker</span></span><br><span class="line">        Invoker invoker = <span class="keyword">new</span> Invoker();</span><br><span class="line">        invoker.setCommand(command);</span><br><span class="line">        <span class="comment">// Client端测试一下</span></span><br><span class="line">        invoker.excuteCommmand();</span><br><span class="line">        invoker.undoCommand();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2>解释器模式</h2>
<p>解释器模式（Interpreter Pattern) 提供了评估语言的语法或表达式的方式，它属于行为型模式。这种模式实现了一个表达式接口，该接口解释一个特定的上下文。这种模式被用在SQL解析， 符号处理引擎等。给定一个语言，定义它的文法表示，并定义一个解释器，这个解释器使用该标识来解释语言中的句子。</p>
<p>例如： 你有买两个水果，苹果和香蕉，苹果10元一千克，香蕉一元一个，单位不统一，这样你就需要进行转换成相同的单位的，再进行计算。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Context</span> </span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">double</span> apple;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">double</span> banana;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Context</span><span class="params">(<span class="keyword">double</span> apple, <span class="keyword">double</span> banana)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.apple = apple;</span><br><span class="line">        <span class="keyword">this</span>.banana = banana;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">interface</span> <span class="title">Interpreter</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">double</span> <span class="title">interpreter</span><span class="params">(Context context)</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//转成以一起重量单位计算</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">WeightInterpreter</span> <span class="keyword">implements</span> <span class="title">Interpreter</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">double</span> <span class="title">interpreter</span><span class="params">(Context context)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> (context.apple + context.banana * <span class="number">5</span>) / <span class="number">2</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//转成以一起个数单位计算</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">CountInterpreter</span> <span class="keyword">implements</span> <span class="title">Interpreter</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">double</span> <span class="title">interpreter</span><span class="params">(Context context)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> (context.apple / <span class="number">5</span> + context.banana) / <span class="number">2</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 计算9+2-8的值</span></span><br><span class="line">        Interpreter interpreter = <span class="keyword">new</span> WeightInterpreter();</span><br><span class="line">        <span class="keyword">double</span> d = interpreter.interpreter(<span class="keyword">new</span> Context(<span class="number">10</span>, <span class="number">1</span>));</span><br><span class="line">        System.out.println(<span class="string">"平均多少钱一千克： "</span> + d);</span><br><span class="line">        interpreter = <span class="keyword">new</span> CountInterpreter();</span><br><span class="line">        d = interpreter.interpreter(<span class="keyword">new</span> Context(<span class="number">10</span>, <span class="number">1</span>));</span><br><span class="line">        System.out.println(<span class="string">"平均多少钱一个： "</span> + d);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>总结</strong></p>
<ol>
<li>
<p>主要解决： 对于一些固定文法构建一个解释句子的解释器。</p>
</li>
<li>
<p>何时使用： 如果一种特定类型的问题发生的频率足够高，那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器，该解释器通过解释这些句子来解决该问题。</p>
</li>
<li>
<p>应用实例： 编译器， 运算表达式计算。</p>
</li>
<li>
<p>优点：</p>
<ol>
<li>可扩展性比较好，灵活。</li>
<li>增加了新的解释表达式的方式。</li>
<li>易于实现简单文法。</li>
</ol>
</li>
<li>
<p>缺点：</p>
<ol>
<li>可利用场景比较少。</li>
<li>对于复杂的文法比较难维护。</li>
<li>解释器模式会引起类膨胀。</li>
<li>解释器模式采用递归调用方法。</li>
</ol>
</li>
<li>
<p>使用场景：</p>
<ol>
<li>可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。</li>
<li>一些重复出现的问题可以用一种简单的语言来进行表达。</li>
<li>一个简单语法需要解释的场景。</li>
</ol>
</li>
</ol>
<h2>中介者模式</h2>
<p><strong>中介者模式（Mediator) 的定义</strong></p>
<p>用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用，从而使其耦合松散，而且可以独立地改变它们之间的交互。</p>
<p>例如： 卖房中介，与买房和卖房者，买房和卖房之间的交易通信都是中介进行的。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">People</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">say</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BuyPeople</span> <span class="keyword">implements</span> <span class="title">People</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">say</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"我要买房"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SellPeople</span> <span class="keyword">implements</span> <span class="title">People</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">say</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"我要卖房"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Mediator</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">transform</span><span class="params">(People people)</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">HouseMediator</span> <span class="keyword">implements</span> <span class="title">Mediator</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> List&lt;People&gt; list = <span class="keyword">new</span> LinkedList&lt;&gt;();</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">transform</span><span class="params">(People people)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (!list.contains(people)) &#123;</span><br><span class="line">            list.add(people);</span><br><span class="line">        &#125;</span><br><span class="line">        people.say();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Mediator mediator = <span class="keyword">new</span> HouseMediator();</span><br><span class="line">        mediator.transform(<span class="keyword">new</span> SellPeople());</span><br><span class="line">        mediator.transform(<span class="keyword">new</span> BuyPeople());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>总结</strong></p>
<ol>
<li>
<p>优点</p>
<ol>
<li>解耦，把同事类原来一对多的依赖变成一对一的依赖，降低同事类的耦合度，同时也符合了迪米特原则。</li>
</ol>
</li>
<li>
<p>缺点</p>
<ol>
<li>中介者模式把业务流程和协调都写在中介者，当同事类越多，中介者的业务就越复杂，造成不好管理的弊端。</li>
<li>中介者模式还有一个明显的缺点，如果要增减同事类，必须得修改抽象中介者角色和具体中介者角色类。</li>
</ol>
</li>
<li>
<p>适用性</p>
<ol>
<li>一组对象以定义良好但是复杂的方式进行通信，产生的相互依赖关系结构混乱且难以理解。</li>
<li>一个对象引用其他很多对象并且直接与这些对象通信，导致难以复用该对象。</li>
<li>想定制一个分布在多个类中的行为，但又不想生成太多的子类。</li>
</ol>
</li>
</ol>
<h2>备忘录模式</h2>
<p>备忘录模式，即保存某个对象内部状态的拷贝，这样以后就可以将该对象恢复到原先的状态，实际上就是将内部的状态进行保存，在需要的时候进行恢复。</p>
<p><strong>结构</strong></p>
<ul>
<li>发起者角色（Originator)： 负责创建一个备忘录用以记录当前时刻它的内部状态，并可以使用备忘录恢复内部状态</li>
<li>备忘录角色（Memento)： 负责存储Originator对象的内部状态，并可以防止Originator以外的其他对象访问备忘录</li>
<li>管理者角色（CareTake)： 负责保存好备忘录</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//备忘录</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Memento</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> String value;</span><br><span class="line">    Memento(String value) &#123;</span><br><span class="line">        <span class="keyword">this</span>.value = value;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function">String <span class="title">getValue</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> value;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">setValue</span><span class="params">(String value)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.value = value;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//备忘录发起者</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Originator</span> </span>&#123;</span><br><span class="line">    <span class="comment">//内部属性</span></span><br><span class="line">    <span class="keyword">private</span> String value;</span><br><span class="line">    Originator(String value) &#123;</span><br><span class="line">        <span class="keyword">this</span>.value = value;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function">String <span class="title">getValue</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> value;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">setValue</span><span class="params">(String value)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.value = value;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//创建备忘录</span></span><br><span class="line">    <span class="function">Memento <span class="title">createMemento</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> Memento(value);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//恢复</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">restoreMemento</span><span class="params">(Memento memento)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.value = memento.getValue();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//管理者</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">CareTake</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> Memento memento;</span><br><span class="line">    CareTake(Memento memento) &#123;</span><br><span class="line">        <span class="keyword">this</span>.memento = memento;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function">Memento <span class="title">getMemento</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> memento;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">setMemento</span><span class="params">(Memento memento)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.memento = memento;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行……</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 创建原始类</span></span><br><span class="line">        Original origi = <span class="keyword">new</span> Original(<span class="string">"egg"</span>);</span><br><span class="line">        <span class="comment">// 创建备忘录</span></span><br><span class="line">        Memento memento = origi.createMemento();</span><br><span class="line">        <span class="comment">//保存备忘录</span></span><br><span class="line">        CareTake careTake = <span class="keyword">new</span> CareTake(memento);</span><br><span class="line">        <span class="comment">// 修改原始类的状态</span></span><br><span class="line">        System.out.println(<span class="string">"初始化状态为： "</span> + origi.getValue());</span><br><span class="line">        origi.setValue(<span class="string">"niu"</span>);</span><br><span class="line">        System.out.println(<span class="string">"修改后的状态为： "</span> + origi.getValue());</span><br><span class="line">        <span class="comment">// 回复原始类的状态</span></span><br><span class="line">        origi.restoreMemento(storage.getMemento());</span><br><span class="line">        System.out.println(<span class="string">"恢复后的状态为： "</span> + origi.getValue());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>总结</strong></p>
<ol>
<li>
<p>当备忘点较多时</p>
<ol>
<li>设置栈将备忘点压栈</li>
<li>将多个备忘录对象持久化和序列化保存到本地</li>
</ol>
</li>
<li>
<p>优点</p>
<ol>
<li>备忘录模式可以把发起人内部信息对象屏蔽起来，从而可以保持封装的边界</li>
<li>简化了发起人类。当发起人角色的状态改变的时候，有可能这个状态无效，这时候就可以使用暂时存储起来的备忘录将状态复原</li>
</ol>
</li>
<li>
<p>缺点</p>
<ol>
<li>如果状态需要完整地存储到备忘录对象中，那么在资源消耗上面备忘录对象比较昂贵</li>
<li>当发起者对象的状态改变的时候，有可能这个协议无效。如果状态改变的成功率达不到要求，可以考虑采取&quot;假如”协议模式</li>
</ol>
</li>
<li>
<p>开发中的应用场景</p>
<ol>
<li>数据库事务管理中的回滚操作</li>
<li>文本编译器中的Ctrl+z回退操作</li>
</ol>
</li>
</ol>
<h2>观察者模式</h2>
<p>在对象之间定义了一对多的依赖，这样一来，当一个对象改变状态，依赖它的对象会收到通知并自动更新。其实就是发布订阅模式，发布者发布信息，订阅者获取信息，订阅了就能收到信息，没订阅就收不到信息。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//观察者</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Observer</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">update</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Observer1</span> <span class="keyword">implements</span> <span class="title">Observer</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">update</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"observer1 has received!"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Observer2</span> <span class="keyword">implements</span> <span class="title">Observer</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">update</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"observer2 has received!"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//被观察者</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Subject</span> </span>&#123;</span><br><span class="line">    <span class="comment">//增加观察者</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">add</span><span class="params">(Observer observer)</span></span>;</span><br><span class="line">    <span class="comment">//删除观察者</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">del</span><span class="params">(Observer observer)</span></span>;</span><br><span class="line">    <span class="comment">//通知所有的观察者</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">notifyObservers</span><span class="params">()</span></span>;</span><br><span class="line">    <span class="comment">//自身的操作</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">operation</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">AbstractSubject</span> <span class="keyword">implements</span> <span class="title">Subject</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> Vector&lt;Observer&gt; vector = <span class="keyword">new</span> Vector&lt;Observer&gt;();</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">add</span><span class="params">(Observer observer)</span> </span>&#123;</span><br><span class="line">        vector.add(observer);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">del</span><span class="params">(Observer observer)</span> </span>&#123;</span><br><span class="line">        vector.remove(observer);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">notifyObservers</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        Enumeration&lt;Observer&gt; enumo = vector.elements();</span><br><span class="line">        <span class="keyword">while</span> (enumo.hasMoreElements()) &#123;</span><br><span class="line">            enumo.nextElement().update();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MySubject</span> <span class="keyword">extends</span> <span class="title">AbstractSubject</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">operation</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"update policy!"</span>);</span><br><span class="line">        notifyObservers();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行……</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ObserverTest</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Subject sub = <span class="keyword">new</span> MySubject();</span><br><span class="line">        sub.add(<span class="keyword">new</span> Observer1());</span><br><span class="line">        sub.add(<span class="keyword">new</span> Observer2());</span><br><span class="line">        sub.operation();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2>状态模式</h2>
<p>状态模式，又称状态对象模式（Pattern of Objects for States)，状态模式是对象的行为模式。<strong>状态模式允许一个对象在其内部状态改变的时候改变其行为</strong>。这个对象看上去就像是改变了它的类一样。</p>
<p>例如： 我们经常在售卖机买东西，收货机会有，等待状态，选货状态，然后是付款，最后是出货。只有这样我们才能买东西。</p>
<p><strong>传统的实现</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SellMachine</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> <span class="keyword">static</span> <span class="keyword">int</span> WAIT = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> <span class="keyword">static</span> <span class="keyword">int</span> SELECT = <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> <span class="keyword">static</span> <span class="keyword">int</span> PAY = <span class="number">2</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> <span class="keyword">static</span> <span class="keyword">int</span> PICK_UP = <span class="number">3</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> status;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">SellMachine</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.status = WAIT;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">action</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">switch</span> (status) &#123;</span><br><span class="line">            <span class="keyword">case</span> WAIT:</span><br><span class="line">                System.out.println(<span class="string">"激活"</span>);</span><br><span class="line">                status = SELECT;</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> SELECT:</span><br><span class="line">                System.err.println(<span class="string">"你已激活，但还未选货"</span>);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> PAY:</span><br><span class="line">                System.err.println(<span class="string">"你已激活，选货，但还未支付"</span>);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> PICK_UP:</span><br><span class="line">                System.out.println(<span class="string">"你已激活，选货，支付，但还未取货"</span>);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">select</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">switch</span> (status) &#123;</span><br><span class="line">            <span class="keyword">case</span> WAIT:</span><br><span class="line">                System.err.println(<span class="string">"你还未激活"</span>);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> SELECT:</span><br><span class="line">                System.out.println(<span class="string">"选货"</span>);</span><br><span class="line">                status = PAY;</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> PAY:</span><br><span class="line">                System.err.println(<span class="string">"你已激活，选货，但还未支付"</span>);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> PICK_UP:</span><br><span class="line">                System.err.println(<span class="string">"你已激活，选货，支付，但还未取货"</span>);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">pay</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">switch</span> (status) &#123;</span><br><span class="line">            <span class="keyword">case</span> WAIT:</span><br><span class="line">                System.err.println(<span class="string">"你还未激活"</span>);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> SELECT:</span><br><span class="line">                System.err.println(<span class="string">"你已激活，但还未选货"</span>);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> PAY:</span><br><span class="line">                System.out.println(<span class="string">"支付"</span>);</span><br><span class="line">                status = PICK_UP;</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> PICK_UP:</span><br><span class="line">                System.err.println(<span class="string">"你已激活，选货，支付，但还未取货"</span>);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">pickUp</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">switch</span> (status) &#123;</span><br><span class="line">            <span class="keyword">case</span> WAIT:</span><br><span class="line">                System.err.println(<span class="string">"你还未激活"</span>);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> SELECT:</span><br><span class="line">                System.out.println(<span class="string">"你已激活，但还未选货"</span>);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> PAY:</span><br><span class="line">                System.err.println(<span class="string">"你已激活，选货，但还未支付"</span>);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> PICK_UP:</span><br><span class="line">                System.out.println(<span class="string">"取货"</span>);</span><br><span class="line">                status = WAIT;</span><br><span class="line">                System.out.println(<span class="string">"----------------------"</span>);</span><br><span class="line">                System.out.println(<span class="string">"等待下一个顾客"</span>);</span><br><span class="line">                System.out.println(<span class="string">"----------------------"</span>);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        SellMachine sellMachine = <span class="keyword">new</span> SellMachine();</span><br><span class="line">        <span class="comment">//正常步骤</span></span><br><span class="line">        sellMachine.action();</span><br><span class="line">        sellMachine.select();</span><br><span class="line">        sellMachine.pay();</span><br><span class="line">        sellMachine.pickUp();</span><br><span class="line">        <span class="comment">//步骤出错，不会继续向下执行，直到正确执行，或者被重置</span></span><br><span class="line">        sellMachine.action();</span><br><span class="line">        sellMachine.pickUp();</span><br><span class="line">        sellMachine.action();</span><br><span class="line">        sellMachine.pay();</span><br><span class="line">        sellMachine.select();</span><br><span class="line">        sellMachine.pay();</span><br><span class="line">        sellMachine.pickUp();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这里售货机每次状态会被正确执行时，状态都会被更新，然后继续向下执行，如果相应状态下没有被正确执行，就不会向下执行。但是当我们要对售货机进行升级时添加一种状态，这时候我们要修改大量之前的代码，这显然违背了我们的设计原则： 封装变化原则。</p>
<p>那么上面这种方式存在什么问题呢？ 首先很直观的感受就是：</p>
<ol>
<li>存在大量的<code>switch case</code>语句  当然可以用<code>if else</code>也是一样的。</li>
<li>可扩展性差，并且一旦要加入一种新的状态，那么就会要修改所有的<code>switch case</code>不符合开闭原则。</li>
<li>没有采用面向对象的方式去封装。</li>
</ol>
<p>为了解决上面的问题，我们首先分析项目中变化的部分和不变的部分，抽化出变化的部分，我们发现售货机提供的行为一般是不变的，就是等待，选货，支付，取货。 而售货机的状态是可以变化的，那么我们这个抽出变化的部分，即我们说的状态模式。</p>
<p><strong>状态模式</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">SellMachineStatus</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">action</span><span class="params">()</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">select</span><span class="params">()</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">pay</span><span class="params">()</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">pickUp</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ActionStatus</span> <span class="keyword">implements</span> <span class="title">SellMachineStatus</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">action</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"激活"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">select</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.err.println(<span class="string">"你已激活，但还未选货"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">pay</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.err.println(<span class="string">"你已激活，选货，但还未支付"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">pickUp</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"你已激活，选货，支付，但还未取货"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SelectStatus</span> <span class="keyword">implements</span> <span class="title">SellMachineStatus</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">action</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.err.println(<span class="string">"你还未激活"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">select</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"选货"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">pay</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.err.println(<span class="string">"你已激活，选货，但还未支付"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">pickUp</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"你已激活，选货，支付，但还未取货"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">PayStatus</span> <span class="keyword">implements</span> <span class="title">SellMachineStatus</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">action</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.err.println(<span class="string">"你还未激活"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">select</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.err.println(<span class="string">"你已激活，但还未选货"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">pay</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"支付"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">pickUp</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"你已激活，选货，支付，但还未取货"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">PickUpStatus</span> <span class="keyword">implements</span> <span class="title">SellMachineStatus</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">action</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.err.println(<span class="string">"你还未激活"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">select</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.err.println(<span class="string">"你已激活，但还未选货"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">pay</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.err.println(<span class="string">"你已激活，选货，但还未支付"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">pickUp</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"取货"</span>);</span><br><span class="line">        System.out.println(<span class="string">"----------------------"</span>);</span><br><span class="line">        System.out.println(<span class="string">"等待下一个顾客"</span>);</span><br><span class="line">        System.out.println(<span class="string">"----------------------"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SellMachine</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> <span class="keyword">static</span> SellMachineStatus WAIT = <span class="keyword">new</span> ActionStatus();</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> <span class="keyword">static</span> SellMachineStatus SELECT = <span class="keyword">new</span> SelectStatus();</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> <span class="keyword">static</span> SellMachineStatus PAY = <span class="keyword">new</span> PayStatus();</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> <span class="keyword">static</span> SellMachineStatus PICK_UP = <span class="keyword">new</span> PickUpStatus();</span><br><span class="line">    <span class="keyword">private</span> SellMachineStatus status;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">SellMachine</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.status = WAIT;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">action</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        status.action();</span><br><span class="line">        status = SELECT;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">select</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        status.select();</span><br><span class="line">        status = PAY;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">pay</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        status.pay();</span><br><span class="line">        status = PICK_UP;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">pickUp</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        status.pickUp();</span><br><span class="line">        status = WAIT;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        SellMachine sellMachine = <span class="keyword">new</span> SellMachine();</span><br><span class="line">        <span class="comment">//正常步骤</span></span><br><span class="line">        sellMachine.action();</span><br><span class="line">        sellMachine.select();</span><br><span class="line">        sellMachine.pay();</span><br><span class="line">        sellMachine.pickUp();</span><br><span class="line">        <span class="comment">//步骤出错，不会继续向下执行，直到正确执行，或者被重置</span></span><br><span class="line">        sellMachine.action();</span><br><span class="line">        sellMachine.pickUp();</span><br><span class="line">        sellMachine.action();</span><br><span class="line">        sellMachine.pay();</span><br><span class="line">        sellMachine.select();</span><br><span class="line">        sellMachine.pay();</span><br><span class="line">        sellMachine.pickUp();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>可以和开始的传统方案对比，结果是一样的，但是具备了可扩展性。</p>
<p><strong>总结</strong></p>
<ol>
<li>状态模式主要针对于具有固定行为，对于不同的行为进行切换。不同的行为之间称之为状态。</li>
<li>状态模式允许对象在内部状态改变时改变它的行为，对象看起来好像改变了它的类，和状态的扩展性也是比传统模式更好。</li>
<li>将容易产生问题的<code>if else</code>和<code>switch case</code>结构去掉，使得代码的可维护性更强，不易出错。使用多态代替了条件判断，这样我们代码的扩展性更强，当要增加一些状态时，会非常的容易。</li>
<li>让每一个状态对修改关闭，对扩展开放。</li>
<li>状态是可以被共享的，因为状态类一般是没有自己的内部状态的，所有它只是一个具有行为的对象，因此是可以被共享的。</li>
<li>状态的转换更加简单安全，简单体现在状态的分割，因为我们把一堆<code>if else</code>和<code>switch case</code>分割成了若干个代码段分别放在几个具体的状态类当中，所以转换起来当然更简单，而且每次转换的时候我们只需要关注一个固定的状态到其他状态的转换。安全体现在类型安全，我们设置状态时，必须是状态接口的实现类，而不是原本的一个整数，这可以杜绝数不正确的状态码。</li>
</ol>
<h2>策略模式</h2>
<p>其思想是针对一组算法，将每一种算法都封装到具有共同接口的独立的类中，从而是它们可以相互替换。策略模式的最大特点是使得算法可以在不影响客户端的情况下发生变化，从而改变不同的功能。</p>
<p>例如： 我们数学中的加减乘除运算</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Calculator</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">int</span> <span class="title">calculate</span><span class="params">(<span class="keyword">int</span> a, <span class="keyword">int</span> b)</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Div</span> <span class="keyword">implements</span> <span class="title">Calculator</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">calculate</span><span class="params">(<span class="keyword">int</span> a, <span class="keyword">int</span> b)</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"使用除法计算方法"</span>);</span><br><span class="line">        <span class="keyword">return</span> a / b;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Mul</span> <span class="keyword">implements</span> <span class="title">Calculator</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">calculate</span><span class="params">(<span class="keyword">int</span> a, <span class="keyword">int</span> b)</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"使用乘法方法"</span>);</span><br><span class="line">        <span class="keyword">return</span> a * b;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Minus</span> <span class="keyword">implements</span> <span class="title">Calculator</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">calculate</span><span class="params">(<span class="keyword">int</span> a, <span class="keyword">int</span> b)</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"使用减法方法"</span>);</span><br><span class="line">        <span class="keyword">return</span> a - b;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Plus</span> <span class="keyword">implements</span> <span class="title">ICalculator</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">calculate</span><span class="params">(<span class="keyword">int</span> a, <span class="keyword">int</span> b)</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"使用加法方法"</span>);</span><br><span class="line">        <span class="keyword">return</span> a + b;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行……</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> a = <span class="number">10</span>, b = <span class="number">2</span>;</span><br><span class="line">        ICalculator calculator = <span class="keyword">new</span> Plus();</span><br><span class="line">        calculator.calculate(a, b);</span><br><span class="line">        calculator = <span class="keyword">new</span> Multiply();</span><br><span class="line">        calculator.calculate(a, b);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2>访问者模式</h2>
<p>访问者模式是一种较为复杂的行为型设计模式，它包含访问者和被访问元素两个主要组成部分，这些被访问的元素通常具有不同的类型，且不同的访问者可以对它们进行不同的访问操作。</p>
<p>在使用访问者模式时，被访问元素通常不是单独存在的，它们存储在一个集合中，这个集合被称为&quot;对象结构”，访问者通过遍历对象结构实现对其中存储的元素的逐个操作。</p>
<p><strong>访问者模式定义如下</strong></p>
<p>访问者模式（Visitor Pattern)： 提供一个作用于某对象结构中的各元素的操作表示，它使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。访问者模式是一种对象行为型模式。</p>
<p>例如： 当你去医院看病，你手上有不同看病单据，不同的医生都可以通过你的单据查出你的信息。这里不同单据是被访问者，不同的医生是访问者，刚好你是持有所有单据的人，你是持有被访问者的一个集合。医生对你的单据进行查询，相当于访问者对被访问者的操作。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">//被访问者</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Subject</span> </span>&#123;</span><br><span class="line">    <span class="comment">//接受一个Visitor</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">accept</span><span class="params">(Visitor visitor)</span></span>;</span><br><span class="line">    <span class="comment">//具体操作</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">show</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ASubject</span> <span class="keyword">implements</span> <span class="title">Subject</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">accept</span><span class="params">(Visitor visitor)</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"A Subject"</span>);</span><br><span class="line">        visitor.visit(<span class="keyword">this</span>);</span><br><span class="line">        visitor.visitA(<span class="keyword">this</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">show</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"我是A"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BSubject</span> <span class="keyword">implements</span> <span class="title">Subject</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">accept</span><span class="params">(Visitor visitor)</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"B Subject"</span>);</span><br><span class="line">        visitor.visit(<span class="keyword">this</span>);</span><br><span class="line">        visitor.visitB(<span class="keyword">this</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">show</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"我是B"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//访问者</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Visitor</span> </span>&#123;</span><br><span class="line">    <span class="comment">//访问一个通用Subject</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">visit</span><span class="params">(Subject subject)</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">visitA</span><span class="params">(ASubject aSubject)</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">visitB</span><span class="params">(BSubject bSubject)</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyVisitor</span> <span class="keyword">implements</span> <span class="title">Visitor</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">visit</span><span class="params">(Subject subject)</span> </span>&#123;</span><br><span class="line">        System.out.print(<span class="string">"通用的访问： "</span>);</span><br><span class="line">        subject.show();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">visitA</span><span class="params">(ASubject aSubject)</span> </span>&#123;</span><br><span class="line">        System.out.print(<span class="string">"专门访问A: "</span>);</span><br><span class="line">        aSubject.show();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">visitB</span><span class="params">(BSubject bSubject)</span> </span>&#123;</span><br><span class="line">        System.out.print(<span class="string">"专门访问B: "</span>);</span><br><span class="line">        bSubject.show();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">AllSubject</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> List&lt;Subject&gt; list = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">iterator</span><span class="params">(Visitor visitor)</span> </span>&#123;</span><br><span class="line">        list.forEach(e -&gt; &#123;</span><br><span class="line">            e.accept(visitor);</span><br><span class="line">        &#125;);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">add</span><span class="params">(Subject... subjects)</span> </span>&#123;</span><br><span class="line">        list.addAll(Arrays.asList(subjects));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">remove</span><span class="params">(Subject subject)</span> </span>&#123;</span><br><span class="line">        list.remove(subject);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Visitor visitor = <span class="keyword">new</span> MyVisitor();</span><br><span class="line">        Subject a = <span class="keyword">new</span> ASubject(), b = <span class="keyword">new</span> BSubject();</span><br><span class="line">        AllSubject allSubject = <span class="keyword">new</span> AllSubject();</span><br><span class="line">        allSubject.add(a, b);</span><br><span class="line">        allSubject.iterator(visitor);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>总结</strong></p>
<p>由于访问者模式的使用条件较为苛刻，本身结构也较为复杂，因此在实际应用中使用频率不是特别高。当系统中存在一个较为复杂的对象结构，且不同访问者对其所采取的操作也不相同时，可以考虑使用访问者模式进行设计。在XML文档解析， 编译器的设计， 复杂集合对象的处理等领域访问者模式得到了一定的应用。</p>
<ol>
<li>
<p>主要优点</p>
<ol>
<li>增加新的访问操作很方便。使用访问者模式，增加新的访问操作就意味着增加一个新的具体访问者类，实现简单，无须修改源代码，符合&quot;开闭原则”。</li>
<li>将有关元素对象的访问行为集中到一个访问者对象中，而不是分散在一个个的元素类中。类的职责更加清晰，有利于对象结构中元素对象的复用，相同的对象结构可以供多个不同的访问者访问。</li>
<li>让用户能够在不修改现有元素类层次结构的情况下，定义作用于该层次结构的操作。</li>
</ol>
</li>
<li>
<p>主要缺点</p>
<ol>
<li>增加新的元素类很困难。在访问者模式中，每增加一个新的元素类都意味着要在抽象访问者角色中增加一个新的抽象操作，并在每一个具体访问者类中增加相应的具体操作，这违背了&quot;开闭原则”的要求。</li>
<li>破坏封装。访问者模式要求访问者对象访问并调用每一个元素对象的操作，这意味着元素对象有时候必须暴露一些自己的内部操作和内部状态，否则无法供访问者访问。我觉得这里把这里需要的操作规划的接口层去，就比较好。</li>
</ol>
</li>
<li>
<p>适用场景</p>
<ol>
<li>一个对象结构包含多个类型的对象，希望对这些对象实施一些依赖其具体类型的操作。在访问者中针对每一种具体的类型都提供了一个访问操作，不同类型的对象可以有不同的访问操作。</li>
<li>需要对一个对象结构中的对象进行很多不同的并且不相关的操作，而需要避免让这些操作&quot;污染”这些对象的类，也不希望在增加新操作时修改这些类。访问者模式使得我们可以将相关的访问操作集中起来定义在访问者类中，对象结构可以被多个不同的访问者类所使用，将对象本身与对象的访问操作分离。</li>
<li>对象结构中对象对应的类很少改变，但经常需要在此对象结构上定义新的操作。</li>
</ol>
</li>
</ol>
<h1>AOP</h1>
<h2>一个简单的约定游戏来阐述AOP</h2>
<h3>约定规则</h3>
<p>首先提供一个拦截器，定义一个Interceptor接口</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Interceptor</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">before</span><span class="params">(Object obj)</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">after</span><span class="params">(Object obj)</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">afterReturning</span><span class="params">(Object obj)</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">afterThrowing</span><span class="params">(Object obj)</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>接下来用这样一个类去生成bean</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ProxyBeanFactory</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span>&lt;T&gt; T <span class="title">getBean</span><span class="params">(T obj ,Interceptor interceptor)</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> (T)ProxyBeanUtil.getBean(obj,intercepter);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><code>ProxyBeanUtil</code>的方法暂时不用去理会，后面会去讲，这里也不讨论拦截器为空的时候，因为这没有什么讨论价值，用了此方法存在如下约定</p>
<ol>
<li>Bean必须是一个实现了某一接口的对象</li>
<li>最先执行拦截器的<code>before</code>方法</li>
<li>其次执行<code>Bean</code>方法（通过反射形式）</li>
<li><code>bean</code>方法执行完之后无论是否有异常都会执行<code>after</code></li>
<li><code>bean</code>方法执行没有异常，则执行<code>afterReturning</code>，否则执行<code>afterThrowing</code></li>
</ol>
<p>如此就有了如下流程<br>
<img src="https://img-blog.csdnimg.cn/20181122135133417.png" alt="在这里插入图片描述"></p>
<p>上面讲述了具体规则，下面开始例子使用</p>
<h3>使用</h3>
<p><strong>定义一个接口</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">PoleService</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">printRole</span><span class="params">(Role role)</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>实现此接口</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RoleServiceImpl</span> <span class="keyword">implements</span> <span class="title">RoleService</span></span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">printRole</span><span class="params">(Role role)</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"id:"</span>+role.id+<span class="string">",name:"</span>+role.name);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>实现拦截器</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RoleInterceptor</span> <span class="keyword">implements</span> <span class="title">Interceptor</span></span>&#123;</span><br><span class="line">	<span class="meta">@Override</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">before</span><span class="params">(Object obj)</span> </span>&#123;</span><br><span class="line">		System.out.println(<span class="string">"准备打印信息"</span>);</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="meta">@Override</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">after</span><span class="params">(Object obj)</span> </span>&#123;</span><br><span class="line">		System.out.println(<span class="string">"打印信息完成"</span>);</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="meta">@Override</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">afterReturning</span><span class="params">(Object obj)</span> </span>&#123;</span><br><span class="line">		System.out.println(<span class="string">"一切正常"</span>);</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="meta">@Override</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">agerThrowing</span><span class="params">(Object obj)</span> </span>&#123;</span><br><span class="line">		System.out.println(<span class="string">"打印异常"</span>);</span><br><span class="line">	&#125;</span><br></pre></td></tr></table></figure>
<p><strong>测试约定流程</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">GameMain</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String []args)</span></span>&#123;</span><br><span class="line">        RoleService roleService=<span class="keyword">new</span> RoleServiceImpl();</span><br><span class="line">        Interceptor interceptor=<span class="keyword">new</span> RoleInterceptor();</span><br><span class="line">        <span class="comment">//获取代理对象</span></span><br><span class="line">        RoleService proxy=ProxyBeanFactory.getBean(roleService,interceptor);</span><br><span class="line">        Role role=<span class="keyword">new</span> Role(<span class="number">1</span>,<span class="string">"MyName"</span>);</span><br><span class="line">        proxy.printRole(role);</span><br><span class="line">        <span class="comment">//测试为空</span></span><br><span class="line">        role=<span class="keyword">null</span>。</span><br><span class="line">        proxy.printRole(role);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>打印结果</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">准备打印信息</span><br><span class="line">id:1,name:MyName</span><br><span class="line">打印信息完成</span><br><span class="line">一切正常</span><br><span class="line">准备打印信息</span><br><span class="line">打印信息完成</span><br><span class="line">打印异常</span><br></pre></td></tr></table></figure>
<p>这里结果就跟我们约定的流程是一样的</p>
<h2>讲述</h2>
<p><code>ProxyBeanUtil</code>类里面的方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ProxyBeanUtil</span> <span class="keyword">implements</span> <span class="title">InvocationHandler</span></span>&#123;</span><br><span class="line">    <span class="comment">//保存被代理对象</span></span><br><span class="line">    <span class="keyword">private</span> Object obj;</span><br><span class="line">    <span class="comment">//拦截器</span></span><br><span class="line">    <span class="keyword">private</span> Interceptor interceptor;</span><br><span class="line">    <span class="comment">//获取动态代理对象</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Object <span class="title">getBean</span><span class="params">(Object obj,Interceptor interceptor)</span></span>&#123;</span><br><span class="line">        ProxyBeanUtil _this=<span class="keyword">new</span> ProxyBeanUtil();</span><br><span class="line">        <span class="comment">//保存被代理对象</span></span><br><span class="line">        _this.obj=obj;</span><br><span class="line">        <span class="comment">//保存拦截器</span></span><br><span class="line">        _this.interceptor=interceptor;</span><br><span class="line">        <span class="comment">//获取动态代理对象</span></span><br><span class="line">        <span class="keyword">return</span> Proxy.newProxyInstance(obj.getClass().getClassLoader(),</span><br><span class="line">                                     obj.getClass().getInterfaces(),_this);</span><br><span class="line">	&#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Object <span class="title">invoke</span><span class="params">(Object proxy,Method method,Object []args)</span><span class="keyword">throws</span> Throwable</span>&#123;</span><br><span class="line">        Object reObj=<span class="keyword">null</span>;</span><br><span class="line">        <span class="comment">//是否产生异常</span></span><br><span class="line">        <span class="keyword">boolean</span> exceptionFlag=<span class="keyword">false</span>;</span><br><span class="line">        <span class="comment">//before</span></span><br><span class="line">        interceptor.before(obj);</span><br><span class="line">        <span class="keyword">try</span>&#123;</span><br><span class="line">            <span class="comment">//反射原有方法</span></span><br><span class="line">            retObj=method.invoke(obj,args);</span><br><span class="line">        &#125;<span class="keyword">catch</span>(Exception ex)&#123;</span><br><span class="line">            exceptionFlag=<span class="keyword">true</span>;</span><br><span class="line">        &#125;<span class="keyword">finally</span>&#123;</span><br><span class="line">            <span class="comment">//after</span></span><br><span class="line">            interceptor.after(obj);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span>(exceptionFlag)</span><br><span class="line">            <span class="comment">//afterThrowing</span></span><br><span class="line">            interceptor.afterThrowing(obj);</span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">            <span class="comment">//afterReturning</span></span><br><span class="line">            interceptor.agterReturning(obj);</span><br><span class="line">        <span class="keyword">return</span> retObj;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>上面代码使用了动态代理，我们讲述下它的流程</p>
<ol>
<li>通过了<code>getBean</code>保存了被代理对象，拦截器（interceptor）和参数（args）</li>
<li>生成了JDK动态代理生成代理对象（proxy）同事绑定了<code>ProxyBeanUtil</code>返回对象作为代理类</li>
<li>于是代理对象调用方法时，就会进入<code>ProxyBeanUtil</code>的<code>invoke</code>方法中</li>
<li><code>invoke</code>实现了我们约定的流程</li>
</ol>
<p><strong>这个例子简单讲述了spring框架的aop的流程，只要抓住了约定内容就不难理解了</strong></p>
<h2>Spring AOP基本概念</h2>
<h3>AOP的使用原因</h3>
<p>当我们做数据库操作的时候，我们就通过底下这几个步骤</p>
<ol>
<li>获取数据连接</li>
<li>业务操作</li>
<li>如出现异常则回滚事务</li>
<li>如成功则提交事务</li>
<li>关闭连接</li>
</ol>
<p>这是不是跟上面的流程很像，AOP就是把这些操作分开来处理，保证了代码简洁，易于维护。这里Spring AOP只需要让我们自己实现业务操作就行，其它的操作都不需要操心，这比起以前的一大堆了try,catch是否好的多</p>
<p><strong>示例代码</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Autowired</span></span><br><span class="line"><span class="keyword">private</span> ProductMapper productMapper =<span class="keyword">null</span>;</span><br><span class="line"><span class="meta">@Autowired</span></span><br><span class="line"><span class="keyword">private</span> PurchaseRecordMapper purchaseRecordMapper=<span class="keyword">null</span>;</span><br><span class="line">······</span><br><span class="line"><span class="meta">@Transactional</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">updateRoleNode</span><span class="params">(Long id,PurchaseRecord record)</span></span>&#123;</span><br><span class="line">	Product p=productMapper.getRole(id);</span><br><span class="line">    <span class="keyword">if</span>(p.getStock()&gt;=record.getQuantity())&#123;</span><br><span class="line">    	<span class="comment">//更新库存</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//保存交易记录</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这里并没有对数据库的链接，关闭等一些操作只有<code>@Transactional</code>,和对业务操作的逻辑处理，这就是AOP的魅力所在</p>
<h3>Spring框架增加了几点约定</h3>
<ul>
<li>当方法标注了<code>@Transactional</code>时，则方法启用数据库事务</li>
<li>在默认情况下，如果原有方法出现异常则回滚事务，否则直接提交事务，这个整套AOP完成了整个流程，开发者无须编写任何代码</li>
<li>关闭数据库资源，AOP框架也可以帮你完成</li>
</ul>
<h3>面向切面编程的术语</h3>
<h4>切面Aspect</h4>
<p>切面就是在一个怎么样的一个环境工作，就比如数据库的事务操作贯穿了整个代码层，这就是一个切面</p>
<p>在动态代理中也可以理解成一个拦截器</p>
<h4>通知Advice</h4>
<ul>
<li>前置通知Before</li>
<li>后置通知after</li>
<li>返回通知afterReturning</li>
<li>异常通知afterThrowing</li>
<li>环绕通知around</li>
</ul>
<p>这里就讲下环绕通知，环绕通知可以替代被代理的原有方法，里面提供调用原有方法。它既有像before的通知，也要像after的通知</p>
<h4>引入Introduction</h4>
<p>引入允许我们现有类里添加自定义方法</p>
<h4>切点Pointcut</h4>
<p>这是告诉Spring AOP在什么时候启用拦截并织入流程，不是所有的方法都需要AOP，它通过正则表达式来限定</p>
<h4>连接点join point</h4>
<p>具体要拦截的方法</p>
<h4>织入</h4>
<p>正如上面游戏的例子，我们使用动态代理的方式将拦截器织入了整套流程中，这里我们织入使用了动态代理的方式，在Spring AOP中使用了两种动态代理</p>
<ul>
<li>JDK动态代理</li>
<li>CGLib动态代理</li>
</ul>
<p>JDK动态代理必须使用接口，而CGLib就不需要，但是Spring会自动根据情况使用哪种代理方式</p>
<p><strong>上面讲述了所有概念和流程，相信大家对AOP有了很好的了解，下面就是Spring AOP的代码实战部分</strong></p>
<h3>使用 @AspectJ注解开发AOP</h3>
<p><strong>选择连接点</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.aop.service;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">PoleService</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">printRole</span><span class="params">(Role role)</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//注意包名</span></span><br><span class="line"><span class="keyword">package</span> com.aop.service.impl;</span><br><span class="line"><span class="comment">//让ioc管理bean</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RoleServiceImpl</span> <span class="keyword">implements</span> <span class="title">RoleService</span></span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">printRole</span><span class="params">(Role role)</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"id:"</span>+role.id+<span class="string">",name:"</span>+role.name);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>创建切面</strong></p>
<ul>
<li>
<h5 id="使用-aspect注解一个类-spring就会认为这是一个切面"><a class="header-anchor" href="#使用-aspect注解一个类-spring就会认为这是一个切面">.</a>使用 @Aspect注解一个类，Spring就会认为这是一个切面</h5>
</li>
</ul>
<p><strong>注意execution里面写的是连接点的方法的全限定名</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RoleAspect</span></span>&#123;</span><br><span class="line">    <span class="comment">/**这里是比较复杂的写法</span></span><br><span class="line"><span class="comment">	<span class="doctag">@Before</span>("execution(*com.aop.serviceImpl.printRole(..))")</span></span><br><span class="line"><span class="comment">	public void before(Object obj) &#123;&#125;</span></span><br><span class="line"><span class="comment">	<span class="doctag">@After</span>("execution(*com.aop.serviceImpl.printRole(..))")</span></span><br><span class="line"><span class="comment">	public void after(Object obj) &#123;&#125;</span></span><br><span class="line"><span class="comment">	<span class="doctag">@AfterReturning</span>("execution(*com.aop.serviceImpl.printRole(..))")</span></span><br><span class="line"><span class="comment">	public void afterReturning(Object obj) &#123;&#125;</span></span><br><span class="line"><span class="comment">	<span class="doctag">@AfterThrowing</span>("execution(*com.aop.serviceImpl.printRole(..))")</span></span><br><span class="line"><span class="comment">	public void agerThrowing(Object obj) &#123;&#125;</span></span><br><span class="line"><span class="comment">	*/</span></span><br><span class="line">    <span class="comment">//这里是简单的写法</span></span><br><span class="line">   	<span class="meta">@Pointcut</span>(<span class="string">"*execution(*com.aop.serviceImpl.printRole(..))"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">print</span><span class="params">()</span></span>&#123;&#125;</span><br><span class="line">	<span class="meta">@Before</span>(<span class="string">"print()"</span>)</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">before</span><span class="params">(Object obj)</span> </span>&#123;</span><br><span class="line">		System.out.println(<span class="string">"before..."</span>);</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="meta">@After</span>(<span class="string">"print()"</span>)</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">after</span><span class="params">(Object obj)</span> </span>&#123;</span><br><span class="line">		System.out.println(<span class="string">"after..."</span>);</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="meta">@AfterReturning</span>(<span class="string">"print()"</span>)</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">afterReturning</span><span class="params">(Object obj)</span> </span>&#123;</span><br><span class="line">		System.out.println(<span class="string">"afterreturn..."</span>);</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="meta">@AfterThrowing</span>(<span class="string">"print()"</span>)</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">agerThrowing</span><span class="params">(Object obj)</span> </span>&#123;</span><br><span class="line">		System.out.println(<span class="string">"afterthrowing"</span>);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>定义切点</strong></p>
<p>不是所有的方法都需要AOP，Spring通过execution里的正则表达式来确定连接点</p>
<ul>
<li>execution代表执行方法时会触发</li>
<li><code>*</code>代表任意返回类型的方法</li>
<li><code>com.aop.serviceImpl</code>类全限定名</li>
<li><code>prinRole</code>被拦截的方法名称</li>
<li>（…）任意参数</li>
</ul>
<p>如果使用了非AspectJ的指示器，就是抛出<code>IllegalArgumentException</code>异常，具体指示器去参加相关文档</p>
<p><strong>使用注解启用自动代理</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="comment">//自动代理</span></span><br><span class="line"><span class="meta">@EnableAspectJAutoProxy</span></span><br><span class="line"><span class="meta">@ComponentScan</span>(<span class="string">"com.aop"</span>)</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">AopConfig</span></span>&#123;</span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> RoleAspect <span class="title">getRoleAspect</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> RoleAspect();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>使用XML启用自动代理</strong></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">beans</span> <span class="attr">xmlns</span>=<span class="string">"http://www.springframework.org/schema/beans"</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:context</span>=<span class="string">"http://www.springframework.org/schema/context"</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:aop</span>=<span class="string">"http://www.springframework.org/schema/aop"</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xsi:schemaLocation</span>=<span class="string">"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 启用Aspectj自动代理--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">aop:aspectj-autoproxy</span> /&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--配置要管理的Bean--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">"roleAspect"</span> <span class="attr">class</span>=<span class="string">"com.aop.Aspect.RoleAspect"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">"roleService"</span> <span class="attr">class</span>=<span class="string">"com.aop.service.impl.RoleService"</span> /&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">beans</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p><strong>测试</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String []args)</span></span>&#123;</span><br><span class="line">    ApplicationContext ctx=<span class="keyword">new</span> AnnotationConfigApplicationContext(AopConfig.class);</span><br><span class="line">    <span class="comment">//使用XML的ClassPathXmlApplicationContext作为ioc容器</span></span><br><span class="line">    <span class="comment">//ApplicationContext ctx=new ClassPathXmlApplicationContext("spring-cfg.xml");</span></span><br><span class="line">    RoleSevice roleSevice=(RoleSevice)ctx.getBean(RoleSevice.class);</span><br><span class="line">    Role role=<span class="keyword">new</span> role(<span class="number">1</span>,<span class="string">"MyName"</span>);</span><br><span class="line">    roleSevice.printRole(role);</span><br><span class="line">    System.out.println(<span class="string">"##################"</span>)</span><br><span class="line">    <span class="comment">//异常测试</span></span><br><span class="line">    role=<span class="keyword">null</span>;</span><br><span class="line">    roleSevice.printRole(role);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>结果</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">before...</span><br><span class="line">id:1,name:MyName</span><br><span class="line">after...</span><br><span class="line">afterreturning...</span><br><span class="line">###################</span><br><span class="line">before...</span><br><span class="line">after...</span><br><span class="line">afterthrowing...</span><br></pre></td></tr></table></figure>
<p>切面通知已经AOP织入约定流程了</p>
<p><strong>加入环绕通知</strong></p>
<p>在切面的类中加入如下代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Arround</span>(<span class="string">"print()"</span>)</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">arround</span><span class="params">(ProceedingJoinPoint jp)</span></span>&#123;</span><br><span class="line">    System.out.println(<span class="string">"around before..."</span>);</span><br><span class="line">    <span class="keyword">try</span>&#123;</span><br><span class="line">        <span class="comment">//执行被代理方法</span></span><br><span class="line">        jp.proceed();</span><br><span class="line">    &#125;<span class="keyword">catch</span>(Throwable e)&#123;</span><br><span class="line">        System.out.println(<span class="string">"环绕通知异常"</span>)</span><br><span class="line">        e.printStackTrace();</span><br><span class="line">    &#125;</span><br><span class="line">    System.out.println(<span class="string">"around after..."</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>结果</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">before...</span><br><span class="line">around before...</span><br><span class="line">id:1,name:MyName</span><br><span class="line">around after...</span><br><span class="line">after...</span><br><span class="line">afterreturning...</span><br><span class="line">###################</span><br><span class="line">before...</span><br><span class="line">after...</span><br><span class="line">afterthrowing...</span><br></pre></td></tr></table></figure>
<p><strong>给通知Aspect传递参数</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Before</span>(<span class="string">"*execution(*com.aop.serviceImpl.printRole(..))&amp;&amp;args(role,sort)"</span>)</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">before</span><span class="params">(Role role,itn sort)</span> </span>&#123;</span><br><span class="line">	System.out.println(<span class="string">"before..."</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>引入</strong></p>
<p>Spring AOP只是通过动态代理技术，把各类通知织入到所约定流程中，而事实上我们需要引入其它的类的方法来得到更好的实现，我就拿上面的例子来说，当Role为null时就不再打印，那么要引入一个新的检测器对其进行检测</p>
<p><strong>示例</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.aop.verifier;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">RoleVerifier</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">verify</span><span class="params">(Role role)</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.aop.verifier.impl;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RoleVerifierImpl</span> <span class="keyword">implements</span> <span class="title">RoleVerifier</span></span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">verify</span><span class="params">(Role role)</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> role!=<span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>接下来就要改写上面的切面<code>RoleAspect</code>这个类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@DeclareParent</span>(value=<span class="string">"com.aop.service.impl.RoleServiceImpl+"</span>,</span><br><span class="line">               defaultImpl=RoleVerifierImpl.class)</span><br><span class="line"><span class="keyword">public</span> RoleVerifier roleVerifier;</span><br></pre></td></tr></table></figure>
<p><strong>注解<code>@DeclareParent</code></strong></p>
<ul>
<li><code>value=&quot;com.aop.service.impl.RoleServiceImpl+&quot;</code>表示对类<code>RoleServiceImpl</code>进行增强，也就是在这个类中引入一个新的接口</li>
<li><code>defaultImpl</code>代表默认的实现类，这里是<code>RoleVerifierImpl</code></li>
</ul>
<p><strong>测试</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String []args)</span></span>&#123;</span><br><span class="line">    ApplicationContext ctx=<span class="keyword">new</span> AnnotationConfigApplicationContext(AopConfig.class);</span><br><span class="line">    RoleSevice roleService=(RoleSevice)ctx.getBean(RoleSevice.class);</span><br><span class="line">    <span class="comment">//转换接口</span></span><br><span class="line">    RoleVerifier roleVerifier=(RoleVerifier)roleService;</span><br><span class="line">    Role role=<span class="keyword">new</span> role(<span class="number">1</span>,<span class="string">"MyName"</span>);</span><br><span class="line">    <span class="keyword">if</span>(roleVerifier.verify(role))&#123;</span><br><span class="line">       	roleSevice.printRole(role);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这里通过强转就可以把接口<code>RoleService</code>转成接口<code>RoleVerifier</code>，然后就可以使用<code>RoleVerifier</code>里面的verify方法了，这里实现是依赖于动态代理实现的，类似这样的代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//生成代理对象并绑定代理方法</span></span><br><span class="line"><span class="keyword">return</span> Proxy.newProxyInstance(obj.getClass().getClassLoader(),</span><br><span class="line">                                     obj.getClass().getInterfaces(),_this);</span><br></pre></td></tr></table></figure>
<p><code>obj.getClass().getInterfaces()</code>意味着代理对象挂在多个接口之下，只要Spring AOP让代理对象挂到<code>RoleVerifier</code>和<code>PoleService</code>那么就可以把对应的Bean通过强转在不同接口相互转换，大家可以自己打断点进行测试</p>
<h3>使用XML配置开发AOP</h3>
<p><strong>选择连接点</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.aop.service;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">PoleService</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">printRole</span><span class="params">(Role role)</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//注意包名</span></span><br><span class="line"><span class="keyword">package</span> com.aop.service.impl;</span><br><span class="line"><span class="comment">//让ioc管理bean</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RoleServiceImpl</span> <span class="keyword">implements</span> <span class="title">RoleService</span></span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">printRole</span><span class="params">(Role role)</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"id:"</span>+role.id+<span class="string">",name:"</span>+role.name);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>创建切面</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.aop.aspect;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RoleAspect</span></span>&#123;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">before</span><span class="params">(Object obj)</span> </span>&#123;</span><br><span class="line">		System.out.println(<span class="string">"before..."</span>);</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">after</span><span class="params">(Object obj)</span> </span>&#123;</span><br><span class="line">		System.out.println(<span class="string">"after..."</span>);</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">afterReturning</span><span class="params">(Object obj)</span> </span>&#123;</span><br><span class="line">		System.out.println(<span class="string">"afterreturn..."</span>);</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">agerThrowing</span><span class="params">(Object obj)</span> </span>&#123;</span><br><span class="line">		System.out.println(<span class="string">"afterthrowing"</span>);</span><br><span class="line">	&#125;</span><br></pre></td></tr></table></figure>
<p><strong>对应配置XML</strong></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">beans</span> <span class="attr">xmlns</span>=<span class="string">"http://www.springframework.org/schema/beans"</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:context</span>=<span class="string">"http://www.springframework.org/schema/context"</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:aop</span>=<span class="string">"http://www.springframework.org/schema/aop"</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xsi:schemaLocation</span>=<span class="string">"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 启用Aspectj自动代理--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">aop:aspectj-autoproxy</span> /&gt;</span></span><br><span class="line">	<span class="comment">&lt;!--引用切面--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">"roleAspect"</span> <span class="attr">class</span>=<span class="string">"com.aop.Aspect.RoleAspect"</span> /&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">"roleService"</span> <span class="attr">class</span>=<span class="string">"com.aop.Service.RoleServiceImpl"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">aop:config</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">aop:aspect</span> <span class="attr">ref</span>=<span class="string">"roleAspect"</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        	<span class="comment">&lt;!--这里一样很麻烦，请看下面</span></span><br><span class="line"><span class="comment">            &lt;aop:before method="before"</span></span><br><span class="line"><span class="comment">                        pointcut="*execution(*com.aop.serviceImpl.printRole(..))" /&gt;</span></span><br><span class="line"><span class="comment">            &lt;aop:after method="after"</span></span><br><span class="line"><span class="comment">                        pointcut="*execution(*com.aop.serviceImpl.printRole(..))" /&gt;</span></span><br><span class="line"><span class="comment">            &lt;aop:after-returning method="afterReturning"</span></span><br><span class="line"><span class="comment">                        pointcut="*execution(*com.aop.serviceImpl.printRole(..))" /&gt;</span></span><br><span class="line"><span class="comment">            &lt;aop:after-throwing method="afterThrowing"</span></span><br><span class="line"><span class="comment">                        pointcut="*execution(*com.aop.serviceImpl.printRole(..))" /&gt;</span></span><br><span class="line"><span class="comment">        	 --&gt;</span></span><br><span class="line">            <span class="comment">&lt;!--定义切点--&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">aop:pointcut</span> <span class="attr">id</span>=<span class="string">"printRole"</span></span></span><br><span class="line"><span class="tag">                          <span class="attr">expression</span>=<span class="string">"execution(*com.aop.serviceImpl.printRole(..))"</span>/&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">aop:before</span> <span class="attr">method</span>=<span class="string">"before"</span> <span class="attr">pointcut-ref</span>=<span class="string">"printRole"</span> /&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">aop:after</span> <span class="attr">method</span>=<span class="string">"after"</span> <span class="attr">pointcut-ref</span>=<span class="string">"printRole"</span> /&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">aop:after-returning</span> <span class="attr">method</span>=<span class="string">"afterReturning"</span> <span class="attr">pointcut-ref</span>=<span class="string">"printRole"</span> /&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">aop:after-throwing</span> <span class="attr">method</span>=<span class="string">"afterThrowing"</span> <span class="attr">pointcut-ref</span>=<span class="string">"printRole"</span> /&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;/<span class="name">aop:aspect</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">aop:config</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">beans</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>定义切点，这里定义和上面一样，只不过这里是写在XML文件中</p>
<p><strong>加入环绕通知</strong></p>
<p>在切面类<code>RoleAspect</code>中加入</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Arround</span>(<span class="string">"print()"</span>)</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">arround</span><span class="params">(ProceedingJoinPoint jp)</span></span>&#123;</span><br><span class="line">    System.out.println(<span class="string">"around before..."</span>);</span><br><span class="line">    <span class="keyword">try</span>&#123;</span><br><span class="line">        <span class="comment">//执行被代理方法</span></span><br><span class="line">        jp.proceed();</span><br><span class="line">    &#125;<span class="keyword">catch</span>(Throwable e)&#123;</span><br><span class="line">        System.out.println(<span class="string">"环绕通知异常"</span>)</span><br><span class="line">        e.printStackTrace();</span><br><span class="line">    &#125;</span><br><span class="line">    System.out.println(<span class="string">"around after..."</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>在上面XML中加入</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">aop:around</span> <span class="attr">method</span>=<span class="string">"around"</span> <span class="attr">pointcut-ref</span>=<span class="string">"printRole"</span>/&gt;</span></span><br></pre></td></tr></table></figure>
<p><strong>测试AOP</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String []args)</span></span>&#123;</span><br><span class="line">    <span class="comment">//使用XML的ClassPathXmlApplicationContext作为ioc容器</span></span><br><span class="line">    ApplicationContext ctx=<span class="keyword">new</span> ClassPathXmlApplicationContext(<span class="string">"spring-cfg.xml"</span>);</span><br><span class="line">    Role role=<span class="keyword">new</span> role(<span class="number">1</span>,<span class="string">"MyName"</span>);</span><br><span class="line">    roleSevice.printRole(role);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>结果就不写了，大家应该都知道了</p>
<p><strong>给通知Aspect传递参数</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Pointcut</span>(<span class="string">"*execution(*com.aop.serviceImpl.printRole(..))&amp;&amp;args(role,sort)"</span>)</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">print</span><span class="params">()</span></span>&#123;&#125;</span><br></pre></td></tr></table></figure>
<p>上面注释部分是使用注解加入参数，这里XML中和注解差不多，只是用and替换了 &amp;&amp;，or替换||，not替换！</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">aop:pointcut</span> <span class="attr">id</span>=<span class="string">"printRole"</span></span></span><br><span class="line"><span class="tag"><span class="attr">expression</span>=<span class="string">"execution(*com.aop.serviceImpl.printRole(..))and args(role,sort)"</span>/&gt;</span></span><br></pre></td></tr></table></figure>
<p><strong>引入</strong></p>
<p>和注解一样，在切面类<code>RoleAspect</code>中加入一个属性<code>RoleVerifier</code></p>
<p>通过XML配置，它使用<code>&lt;aop:declare-parents&gt;</code>去引入的</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">aop:declare-parents</span> <span class="attr">types-matching</span>=<span class="string">"com.aop.service.impl.RoleServiceImpl"</span></span></span><br><span class="line"><span class="tag">                     <span class="attr">implements-interface</span>=<span class="string">"com.aop.verifier.RoleVerifier"</span></span></span><br><span class="line"><span class="tag">                     <span class="attr">default-impl</span>=<span class="string">"com.aop.verifier.RoleVerifierImpl"</span>/&gt;</span></span><br></pre></td></tr></table></figure>
<p>显然它和注解的方式十分接近</p>
<p><strong>测试</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String []args)</span></span>&#123;</span><br><span class="line">    ApplicationContext ctx=<span class="keyword">new</span> ClassPathXmlApplicationContext(<span class="string">"spring-cfg.xml"</span>);</span><br><span class="line">    RoleSevice roleService=(RoleSevice)ctx.getBean(RoleSevice.class);</span><br><span class="line">    <span class="comment">//转换接口</span></span><br><span class="line">    RoleVerifier roleVerifier=(RoleVerifier)roleService;</span><br><span class="line">    Role role=<span class="keyword">new</span> role(<span class="number">1</span>,<span class="string">"MyName"</span>);</span><br><span class="line">    <span class="keyword">if</span>(roleVerifier.verify(role))&#123;</span><br><span class="line">       	roleSevice.printRole(role);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>结果当然和注解是一样的，但是推荐使用注解，注解使用起来方便</p>
<h3>多个切面编写</h3>
<p>上面讲了那么多大家都差不多熟悉了，重点还是在动态代理，下面讲述多个切面，多切面其实就是多个拦截器，贯穿全部来看又称为责任链</p>
<p><strong>代理对象</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.bean;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">MultiBean</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testMulti</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.bean.impl;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MultiBeanImpl</span> <span class="keyword">implements</span> <span class="title">MultiBean</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testMulti</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"test multi aspects"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>三个切面</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.aspect;</span><br><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="meta">@Order</span>(<span class="number">1</span>)</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Aspect1</span></span>&#123;</span><br><span class="line">    <span class="meta">@Pointcut</span>(<span class="string">"execution(*com.bean.impl.testMulti(..))"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test</span><span class="params">()</span></span>&#123;&#125;</span><br><span class="line">    <span class="meta">@Before</span>(<span class="string">"test()"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">before</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"Aspect1 Before ..."</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@After</span>(<span class="string">"test()"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">after</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"Aspect1 After ..."</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@AfterReturning</span>(<span class="string">"test()"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">afterReturning</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"Aspect1 AfterReturning ..."</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@AfterThrowing</span>(<span class="string">"test()"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">afterThrowing</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"Aspect1 AfterThrowing ..."</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.aspect;</span><br><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="meta">@Order</span>(<span class="number">2</span>)</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Aspect2</span></span>&#123;</span><br><span class="line">    <span class="meta">@Pointcut</span>(<span class="string">"execution(*com.bean.impl.testMulti(..))"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test</span><span class="params">()</span></span>&#123;&#125;</span><br><span class="line">    <span class="meta">@Before</span>(<span class="string">"test()"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">before</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"Aspect2 Before ..."</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@After</span>(<span class="string">"test()"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">after</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"Aspect2 After ..."</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@AfterReturning</span>(<span class="string">"test()"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">afterReturning</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"Aspect2 AfterReturning ..."</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@AfterThrowing</span>(<span class="string">"test()"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">afterThrowing</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"Aspect2 AfterThrowing ..."</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.aspect;</span><br><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="meta">@Order</span>(<span class="number">3</span>)</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Aspect3</span></span>&#123;</span><br><span class="line">    <span class="meta">@Pointcut</span>(<span class="string">"execution(*com.bean.impl.testMulti(..))"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test</span><span class="params">()</span></span>&#123;&#125;</span><br><span class="line">    <span class="meta">@Before</span>(<span class="string">"test()"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">before</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"Aspect3 Before ..."</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@After</span>(<span class="string">"test()"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">after</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"Aspect3 After ..."</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@AfterReturning</span>(<span class="string">"test()"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">afterReturning</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"Aspect3 AfterReturning ..."</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@AfterThrowing</span>(<span class="string">"test()"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">afterThrowing</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"Aspect3 AfterThrowing ..."</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>使用注解启用自动代理</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="comment">//自动代理</span></span><br><span class="line"><span class="meta">@EnableAspectJAutoProxy</span></span><br><span class="line"><span class="meta">@ComponentScan</span>(<span class="string">"com.aop"</span>)</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">AopConfigs</span></span>&#123;</span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Aspect1 <span class="title">getAspect1</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> Aspect1();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Aspect1 <span class="title">getAspect1</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> Aspect1();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Aspect1 <span class="title">getAspect1</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> Aspect1();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>测试</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String []args)</span></span>&#123;</span><br><span class="line">    ApplicationContext ctx=<span class="keyword">new</span> AnnotationConfigApplicationContext(AopConfigs.class);</span><br><span class="line">    MultiBeanImpl multiBeanImpl=(MultiBeanImpl)ctx.getBean(MultiBean.class);</span><br><span class="line">    multiBeanImpl.testMulti();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>结果</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">Aspect1 Before ...</span><br><span class="line">Aspect2 Before ...</span><br><span class="line">Aspect3 Before ...</span><br><span class="line">test multi aspects</span><br><span class="line">Aspect3 After ...</span><br><span class="line">Aspect3 AfterReturning ...</span><br><span class="line">Aspect2 After ...</span><br><span class="line">Aspect2 AfterReturning ...</span><br><span class="line">Aspect1 After ...</span><br><span class="line">Aspect1 AfterReturning ...</span><br></pre></td></tr></table></figure>
<p>测试结果真的就真么有序吗，其实不然，它们是无序的，只是我们在类的前面用<code>Order</code>排好了序在Aspect前面有<code>@Order(1)</code>，那么它就是第一个执行，依次类推，除了这种还可以实现Order接口<code>org.springframework.core.Order</code>,它定义了一个<code>getOrder</code>方法可以取代注解<code>@Order</code>，返回多少就第几个</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Aspect1</span></span>&#123;</span><br><span class="line">	<span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getOrder</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    ······</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>xml方式也有</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">······</span><br><span class="line"><span class="tag">&lt;<span class="name">aop:aspect</span> <span class="attr">ref</span>=<span class="string">"aspect1"</span> <span class="attr">order</span>=<span class="string">"1"</span>&gt;</span><span class="tag">&lt;/<span class="name">aop:aspect</span>&gt;</span></span><br><span class="line">······</span><br></pre></td></tr></table></figure>

      
    </div>

    
      





    


    
    
    

    

    
      <div>
        <div style="padding: 10px 0; margin: 20px auto; width: 90%; text-align: center;">
  <div>如果这篇文章对您很有帮助，不妨</div>
  <button id="rewardButton" disable="enable" onclick="var qr = document.getElementById('QR'); if (qr.style.display === 'none') {qr.style.display='block';} else {qr.style.display='none'}">
    <span>打赏</span>
  </button>
  <div id="QR" style="display: none;">

    
      <div id="wechat" style="display: inline-block">
        <img id="wechat_qr" src="/blog/images/wechatpay.png" alt="付祥/lfagon 微信支付">
        <p>微信支付</p>
      </div>
    

    
      <div id="alipay" style="display: inline-block">
        <img id="alipay_qr" src="/blog/images/alipay.jpg" alt="付祥/lfagon 支付宝">
        <p>支付宝</p>
      </div>
    

    

  </div>
</div>

      </div>
    

    
    
    	<div>
	   
             <div>
    
        <div style="margin-top: 30px;text-align:center;color: #ccc;font-size:14px;">-------------　　　　本文结束　<i class="fa fa-heart"></i>　感谢您的阅读　　　　-------------</div>
    
</div>
           
        </div>

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/blog/tags/java/" rel="tag"><i class="fa fa-tag"></i> java</a>
          
            <a href="/blog/tags/设计模式/" rel="tag"><i class="fa fa-tag"></i> 设计模式</a>
          
        </div>
      

      
      
        <div class="post-widgets">
        
          <div class="wp_rating">
            <div style="color: rgba(0, 0, 0, 0.75); font-size:13px; letter-spacing:3px">(&gt;看完记得五星好评哦亲&lt;)</div>
            <div id="wpac-rating"></div>
          </div>
        

        

        
          
          <div id="needsharebutton-postbottom">
            <span class="btn">
              <i class="fa fa-share-alt" aria-hidden="true"></i>
            </span>
          </div>
        
        </div>
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/blog/2019/05/16/log4j使用/" rel="next" title="log4j 使用">
                <i class="fa fa-chevron-left"></i> log4j 使用
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/blog/2019/05/16/maven整体介绍/" rel="prev" title="maven 整体介绍">
                maven 整体介绍 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
        
  <div class="bdsharebuttonbox">
    <a href="#" class="bds_tsina" data-cmd="tsina" title="分享到新浪微博"></a>
    <a href="#" class="bds_douban" data-cmd="douban" title="分享到豆瓣网"></a>
    <a href="#" class="bds_sqq" data-cmd="sqq" title="分享到QQ好友"></a>
    <a href="#" class="bds_qzone" data-cmd="qzone" title="分享到QQ空间"></a>
    <a href="#" class="bds_weixin" data-cmd="weixin" title="分享到微信"></a>
    <a href="#" class="bds_tieba" data-cmd="tieba" title="分享到百度贴吧"></a>
    <a href="#" class="bds_twi" data-cmd="twi" title="分享到Twitter"></a>
    <a href="#" class="bds_fbook" data-cmd="fbook" title="分享到Facebook"></a>
    <a href="#" class="bds_more" data-cmd="more"></a>
    <a class="bds_count" data-cmd="count"></a>
  </div>
  <script>
    window._bd_share_config = {
      "common": {
        "bdText": "",
        "bdMini": "2",
        "bdMiniList": false,
        "bdPic": ""
      },
      "share": {
        "bdSize": "24",
        "bdStyle": "0"
      },
      "image": {
        "viewList": ["tsina", "douban", "sqq", "qzone", "weixin", "twi", "fbook"],
        "viewText": "分享到：",
        "viewSize": "7"
      }
    }
  </script>

<script>
  with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='/static/api/js/share.js?cdnversion='+~(-new Date()/36e5)];
</script>

      
  </div>


          </div>
          

  
    <div class="comments" id="comments">
      
        <div id="gitment-container"></div>
      
    </div>

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image" src="/blog/images/avatar.jpg" alt="付祥/lfagon">
            
              <p class="site-author-name" itemprop="name">付祥/lfagon</p>
              <p class="site-description motion-element" itemprop="description"></p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/blog/archives/">
              
                  <span class="site-state-item-count">77</span>
                  <span class="site-state-item-name">日志</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                <a href="/blog/categories/index.html">
                  <span class="site-state-item-count">6</span>
                  <span class="site-state-item-name">分类</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-tags">
                <a href="/blog/tags/index.html">
                  <span class="site-state-item-count">28</span>
                  <span class="site-state-item-name">标签</span>
                </a>
              </div>
            

          </nav>

          
            <div class="feed-link motion-element">
              <a href="/blog/atom.xml" rel="alternate">
                <i class="fa fa-rss"></i>
                RSS
              </a>
            </div>
          

          
            <div class="links-of-author motion-element">
                
                  <span class="links-of-author-item">
                    <a href="https://github.com/lfagon" target="_blank" title="Github">
                      
                        <i class="fa fa-fw fa-github"></i></a>
                  </span>
                
                  <span class="links-of-author-item">
                    <a href="https://gitee.com/lfagon" target="_blank" title="Gitee">
                      
                        <i class="fa fa-fw fa-git"></i></a>
                  </span>
                
                  <span class="links-of-author-item">
                    <a href="mailto:slash7675@gmail.com" target="_blank" title="E-Mail">
                      
                        <i class="fa fa-fw fa-envelope"></i></a>
                  </span>
                
                  <span class="links-of-author-item">
                    <a href="https://plus.google.com/" target="_blank" title="Google">
                      
                        <i class="fa fa-fw fa-google"></i></a>
                  </span>
                
            </div>
          

          
          
            <div class="cc-license motion-element" itemprop="license">
              <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" class="cc-opacity" target="_blank">
                <img src="/blog/images/cc-by-nc-sa.svg" alt="Creative Commons">
              </a>
            </div>
          

          
          
            <div class="links-of-blogroll motion-element links-of-blogroll-block">
              <div class="links-of-blogroll-title">
                <i class="fa  fa-fw fa-globe"></i>
                圈子里住着一群可爱的程序猿&nbsp;<i class="fa fa-fw fa-globe fa-flip-horizontal"></i>
              </div>
              <ul class="links-of-blogroll-list">
                
                  <li class="links-of-blogroll-item">
                    <a href="https://reuixiy.github.io/" title="一个Hexo博客玩到极致的大佬" target="_blank">一个Hexo博客玩到极致的大佬</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://mmmmasterc.github.io/" title="又菜又爱秀的哥们" target="_blank">又菜又爱秀的哥们</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://www.codesheep.cn/" title="乐于分享的华科Java程序羊(B站up主)" target="_blank">乐于分享的华科Java程序羊(B站up主)</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://me.idealli.com/" title="前端大神自称兰州小红鸡" target="_blank">前端大神自称兰州小红鸡</a>
                  </li>
                
              </ul>
            </div>
          

          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#undefined"><span class="nav-number">1.</span> <span class="nav-text">创建型模式： 对象实例化的模式，创建型模式用于解耦对象的实例化过程</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#undefined"><span class="nav-number">1.1.</span> <span class="nav-text">建造者模式</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#undefined"><span class="nav-number">1.1.1.</span> <span class="nav-text">普通类建造者模式</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#undefined"><span class="nav-number">1.1.2.</span> <span class="nav-text">面向接口建造者模式</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#undefined"><span class="nav-number">1.2.</span> <span class="nav-text">工厂模式</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#undefined"><span class="nav-number">1.2.1.</span> <span class="nav-text">简单工厂</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#undefined"><span class="nav-number">1.2.2.</span> <span class="nav-text">抽象工厂</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#undefined"><span class="nav-number">1.3.</span> <span class="nav-text">原型模式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#undefined"><span class="nav-number">1.4.</span> <span class="nav-text">单例模式</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#undefined"><span class="nav-number">1.4.1.</span> <span class="nav-text">懒汉模式</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#undefined"><span class="nav-number">1.4.2.</span> <span class="nav-text">饿汉模式</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#undefined"><span class="nav-number">2.</span> <span class="nav-text">结构型模式： 把类或对象结合在一起形成一个更大的结构</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#undefined"><span class="nav-number">2.1.</span> <span class="nav-text">适配器模式</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#undefined"><span class="nav-number">2.1.1.</span> <span class="nav-text">接口适配器</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#undefined"><span class="nav-number">2.1.2.</span> <span class="nav-text">类适配器</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#undefined"><span class="nav-number">2.1.3.</span> <span class="nav-text">对象适配器</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#undefined"><span class="nav-number">2.2.</span> <span class="nav-text">桥接模式</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#undefined"><span class="nav-number">2.2.1.</span> <span class="nav-text">一对多桥接</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#undefined"><span class="nav-number">2.2.2.</span> <span class="nav-text">多对多桥接</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#undefined"><span class="nav-number">2.3.</span> <span class="nav-text">组合模式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#undefined"><span class="nav-number">2.4.</span> <span class="nav-text">装饰器模式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#undefined"><span class="nav-number">2.5.</span> <span class="nav-text">外观模式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#undefined"><span class="nav-number">2.6.</span> <span class="nav-text">享元模式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#undefined"><span class="nav-number">2.7.</span> <span class="nav-text">代理模式</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#undefined"><span class="nav-number">2.7.1.</span> <span class="nav-text">普通代理</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#undefined"><span class="nav-number">2.7.2.</span> <span class="nav-text">动态代理</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#undefined"><span class="nav-number">3.</span> <span class="nav-text">行为型模式： 类和对象如何交互，及划分责任和算法</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#undefined"><span class="nav-number">3.1.</span> <span class="nav-text">责任链模式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#undefined"><span class="nav-number">3.2.</span> <span class="nav-text">命令模式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#undefined"><span class="nav-number">3.3.</span> <span class="nav-text">解释器模式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#undefined"><span class="nav-number">3.4.</span> <span class="nav-text">中介者模式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#undefined"><span class="nav-number">3.5.</span> <span class="nav-text">备忘录模式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#undefined"><span class="nav-number">3.6.</span> <span class="nav-text">观察者模式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#undefined"><span class="nav-number">3.7.</span> <span class="nav-text">状态模式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#undefined"><span class="nav-number">3.8.</span> <span class="nav-text">策略模式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#undefined"><span class="nav-number">3.9.</span> <span class="nav-text">访问者模式</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#undefined"><span class="nav-number">4.</span> <span class="nav-text">AOP</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#undefined"><span class="nav-number">4.1.</span> <span class="nav-text">一个简单的约定游戏来阐述AOP</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#undefined"><span class="nav-number">4.1.1.</span> <span class="nav-text">约定规则</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#undefined"><span class="nav-number">4.1.2.</span> <span class="nav-text">使用</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#undefined"><span class="nav-number">4.2.</span> <span class="nav-text">讲述</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#undefined"><span class="nav-number">4.3.</span> <span class="nav-text">Spring AOP基本概念</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#undefined"><span class="nav-number">4.3.1.</span> <span class="nav-text">AOP的使用原因</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#undefined"><span class="nav-number">4.3.2.</span> <span class="nav-text">Spring框架增加了几点约定</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#undefined"><span class="nav-number">4.3.3.</span> <span class="nav-text">面向切面编程的术语</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#undefined"><span class="nav-number">4.3.3.1.</span> <span class="nav-text">切面Aspect</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#undefined"><span class="nav-number">4.3.3.2.</span> <span class="nav-text">通知Advice</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#undefined"><span class="nav-number">4.3.3.3.</span> <span class="nav-text">引入Introduction</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#undefined"><span class="nav-number">4.3.3.4.</span> <span class="nav-text">切点Pointcut</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#undefined"><span class="nav-number">4.3.3.5.</span> <span class="nav-text">连接点join point</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#undefined"><span class="nav-number">4.3.3.6.</span> <span class="nav-text">织入</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#undefined"><span class="nav-number">4.3.4.</span> <span class="nav-text">使用 @AspectJ注解开发AOP</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#使用-aspect注解一个类-spring就会认为这是一个切面"><span class="nav-number">4.3.4.0.1.</span> <span class="nav-text">.使用 @Aspect注解一个类，Spring就会认为这是一个切面</span></a></li></ol></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#undefined"><span class="nav-number">4.3.5.</span> <span class="nav-text">使用XML配置开发AOP</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#undefined"><span class="nav-number">4.3.6.</span> <span class="nav-text">多个切面编写</span></a></li></ol></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      
    </div>
  </aside>


        
      </div>
    </div></main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2019</span>
  <span class="with-love">
    <font color="red"><i class="fa fa-heartbeat" aria-hidden="true"></i></font>
  </span>
  <span class="author" itemprop="copyrightHolder">copyright</span>
  &nbsp;<a href="https://www.oschina.net/"><font size="2px">中国开源社区</font></a>

  
</div>




<div style="width:300px;margin:0 auto; padding:0 0;">
   <a href style="display:inline-block;text-decoration:none;height:20px;line-height:20px;"><img src="/blog/images/icons/record.png" style="float:left;height:90%;width:auto;"><p style="float:left;height:20px;line-height:20px;margin: 0px 0px 0px 5px; color:#939393;letter-spacing:0px"><font size="2px">公网安备 xxxxxxxxxxx号</font></p></a>
</div>





        
<div class="busuanzi-count">
  <script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>

  
    <span class="site-uv">
      <i class="fa fa-user">&nbsp;访客量：</i>
      <span class="busuanzi-value" id="busuanzi_value_site_uv"></span>
      
    </span>
  

  
    <span class="site-pv">
      <i class="fa fa-eye">&nbsp;访问量：</i>
      <span class="busuanzi-value" id="busuanzi_value_site_pv"></span>
      
    </span>
  
</div>




        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
          <span id="scrollpercent"><span>0</span>%</span>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>




















  
  
    <script type="text/javascript" src="/blog/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  


  

  <script type="text/javascript" src="/blog/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/blog/js/src/motion.js?v=5.1.4"></script>

  <script type="text/javascript" src="/blog/js/src/image.js?v=5.1.4"></script>

  <script type="text/javascript" src="/blog/js/src/linkcard.js?v=5.1.4"></script>

  <script type="text/javascript" src="/blog/js/src/clicksocialvalue.js?v=5.1.4"></script>

  <script type="text/javascript" src="/blog/js/src/clicklove.js?v=5.1.4"></script>



  
  

  
  <script type="text/javascript" src="/blog/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/blog/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/blog/js/src/bootstrap.js?v=5.1.4"></script>



  



	





  




  





<!-- LOCAL: You can save these files to your site and update links -->
    
        
        <link rel="stylesheet" href="https://aimingoo.github.io/gitmint/style/default.css">
        <script src="https://aimingoo.github.io/gitmint/dist/gitmint.browser.js"></script>
    
<!-- END LOCAL -->

    

    
      <script type="text/javascript">
      function renderGitment(){
        var gitment = new Gitmint({
            id: window.location.pathname, 
            owner: 'lfagon',
            repo: 'BlogComment',
            
            lang: "" || navigator.language || navigator.systemLanguage || navigator.userLanguage,
            
            oauth: {
            
            
                client_secret: 'de7d4aee11c1d7e4fd0ab75222817a4875fb378c',
            
                client_id: '969cf8ab6443ea4bd042'
            }});
        gitment.render('gitment-container');
      }

      
      renderGitment();
      
      </script>
    





  

  <script type="text/javascript">
    // Popup Window;
    var isfetched = false;
    var isXml = true;
    // Search DB path;
    var search_path = "search.xml";
    if (search_path.length === 0) {
      search_path = "search.xml";
    } else if (/json$/i.test(search_path)) {
      isXml = false;
    }
    var path = "/blog/" + search_path;
    // monitor main search box;

    var onPopupClose = function (e) {
      $('.popup').hide();
      $('#local-search-input').val('');
      $('.search-result-list').remove();
      $('#no-result').remove();
      $(".local-search-pop-overlay").remove();
      $('body').css('overflow', '');
    }

    function proceedsearch() {
      $("body")
        .append('<div class="search-popup-overlay local-search-pop-overlay"></div>')
        .css('overflow', 'hidden');
      $('.search-popup-overlay').click(onPopupClose);
      $('.popup').toggle();
      var $localSearchInput = $('#local-search-input');
      $localSearchInput.attr("autocapitalize", "none");
      $localSearchInput.attr("autocorrect", "off");
      $localSearchInput.focus();
    }

    // search function;
    var searchFunc = function(path, search_id, content_id) {
      'use strict';

      // start loading animation
      $("body")
        .append('<div class="search-popup-overlay local-search-pop-overlay">' +
          '<div id="search-loading-icon">' +
          '<i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>' +
          '</div>' +
          '</div>')
        .css('overflow', 'hidden');
      $("#search-loading-icon").css('margin', '20% auto 0 auto').css('text-align', 'center');

      $.ajax({
        url: path,
        dataType: isXml ? "xml" : "json",
        async: true,
        success: function(res) {
          // get the contents from search data
          isfetched = true;
          $('.popup').detach().appendTo('.header-inner');
          var datas = isXml ? $("entry", res).map(function() {
            return {
              title: $("title", this).text(),
              content: $("content",this).text(),
              url: $("url" , this).text()
            };
          }).get() : res;
          var input = document.getElementById(search_id);
          var resultContent = document.getElementById(content_id);
          var inputEventFunction = function() {
            var searchText = input.value.trim().toLowerCase();
            var keywords = searchText.split(/[\s\-]+/);
            if (keywords.length > 1) {
              keywords.push(searchText);
            }
            var resultItems = [];
            if (searchText.length > 0) {
              // perform local searching
              datas.forEach(function(data) {
                var isMatch = false;
                var hitCount = 0;
                var searchTextCount = 0;
                var title = data.title.trim();
                var titleInLowerCase = title.toLowerCase();
                var content = data.content.trim().replace(/<[^>]+>/g,"");
                var contentInLowerCase = content.toLowerCase();
                var articleUrl = decodeURIComponent(data.url);
                var indexOfTitle = [];
                var indexOfContent = [];
                // only match articles with not empty titles
                if(title != '') {
                  keywords.forEach(function(keyword) {
                    function getIndexByWord(word, text, caseSensitive) {
                      var wordLen = word.length;
                      if (wordLen === 0) {
                        return [];
                      }
                      var startPosition = 0, position = [], index = [];
                      if (!caseSensitive) {
                        text = text.toLowerCase();
                        word = word.toLowerCase();
                      }
                      while ((position = text.indexOf(word, startPosition)) > -1) {
                        index.push({position: position, word: word});
                        startPosition = position + wordLen;
                      }
                      return index;
                    }

                    indexOfTitle = indexOfTitle.concat(getIndexByWord(keyword, titleInLowerCase, false));
                    indexOfContent = indexOfContent.concat(getIndexByWord(keyword, contentInLowerCase, false));
                  });
                  if (indexOfTitle.length > 0 || indexOfContent.length > 0) {
                    isMatch = true;
                    hitCount = indexOfTitle.length + indexOfContent.length;
                  }
                }

                // show search results

                if (isMatch) {
                  // sort index by position of keyword

                  [indexOfTitle, indexOfContent].forEach(function (index) {
                    index.sort(function (itemLeft, itemRight) {
                      if (itemRight.position !== itemLeft.position) {
                        return itemRight.position - itemLeft.position;
                      } else {
                        return itemLeft.word.length - itemRight.word.length;
                      }
                    });
                  });

                  // merge hits into slices

                  function mergeIntoSlice(text, start, end, index) {
                    var item = index[index.length - 1];
                    var position = item.position;
                    var word = item.word;
                    var hits = [];
                    var searchTextCountInSlice = 0;
                    while (position + word.length <= end && index.length != 0) {
                      if (word === searchText) {
                        searchTextCountInSlice++;
                      }
                      hits.push({position: position, length: word.length});
                      var wordEnd = position + word.length;

                      // move to next position of hit

                      index.pop();
                      while (index.length != 0) {
                        item = index[index.length - 1];
                        position = item.position;
                        word = item.word;
                        if (wordEnd > position) {
                          index.pop();
                        } else {
                          break;
                        }
                      }
                    }
                    searchTextCount += searchTextCountInSlice;
                    return {
                      hits: hits,
                      start: start,
                      end: end,
                      searchTextCount: searchTextCountInSlice
                    };
                  }

                  var slicesOfTitle = [];
                  if (indexOfTitle.length != 0) {
                    slicesOfTitle.push(mergeIntoSlice(title, 0, title.length, indexOfTitle));
                  }

                  var slicesOfContent = [];
                  while (indexOfContent.length != 0) {
                    var item = indexOfContent[indexOfContent.length - 1];
                    var position = item.position;
                    var word = item.word;
                    // cut out 100 characters
                    var start = position - 20;
                    var end = position + 80;
                    if(start < 0){
                      start = 0;
                    }
                    if (end < position + word.length) {
                      end = position + word.length;
                    }
                    if(end > content.length){
                      end = content.length;
                    }
                    slicesOfContent.push(mergeIntoSlice(content, start, end, indexOfContent));
                  }

                  // sort slices in content by search text's count and hits' count

                  slicesOfContent.sort(function (sliceLeft, sliceRight) {
                    if (sliceLeft.searchTextCount !== sliceRight.searchTextCount) {
                      return sliceRight.searchTextCount - sliceLeft.searchTextCount;
                    } else if (sliceLeft.hits.length !== sliceRight.hits.length) {
                      return sliceRight.hits.length - sliceLeft.hits.length;
                    } else {
                      return sliceLeft.start - sliceRight.start;
                    }
                  });

                  // select top N slices in content

                  var upperBound = parseInt('1');
                  if (upperBound >= 0) {
                    slicesOfContent = slicesOfContent.slice(0, upperBound);
                  }

                  // highlight title and content

                  function highlightKeyword(text, slice) {
                    var result = '';
                    var prevEnd = slice.start;
                    slice.hits.forEach(function (hit) {
                      result += text.substring(prevEnd, hit.position);
                      var end = hit.position + hit.length;
                      result += '<b class="search-keyword">' + text.substring(hit.position, end) + '</b>';
                      prevEnd = end;
                    });
                    result += text.substring(prevEnd, slice.end);
                    return result;
                  }

                  var resultItem = '';

                  if (slicesOfTitle.length != 0) {
                    resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + highlightKeyword(title, slicesOfTitle[0]) + "</a>";
                  } else {
                    resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + title + "</a>";
                  }

                  slicesOfContent.forEach(function (slice) {
                    resultItem += "<a href='" + articleUrl + "'>" +
                      "<p class=\"search-result\">" + highlightKeyword(content, slice) +
                      "...</p>" + "</a>";
                  });

                  resultItem += "</li>";
                  resultItems.push({
                    item: resultItem,
                    searchTextCount: searchTextCount,
                    hitCount: hitCount,
                    id: resultItems.length
                  });
                }
              })
            };
            if (keywords.length === 1 && keywords[0] === "") {
              resultContent.innerHTML = '<div id="no-result"><i class="fa fa-search fa-5x" /></div>'
            } else if (resultItems.length === 0) {
              resultContent.innerHTML = '<div id="no-result"><i class="fa fa-frown-o fa-5x" /></div>'
            } else {
              resultItems.sort(function (resultLeft, resultRight) {
                if (resultLeft.searchTextCount !== resultRight.searchTextCount) {
                  return resultRight.searchTextCount - resultLeft.searchTextCount;
                } else if (resultLeft.hitCount !== resultRight.hitCount) {
                  return resultRight.hitCount - resultLeft.hitCount;
                } else {
                  return resultRight.id - resultLeft.id;
                }
              });
              var searchResultList = '<ul class=\"search-result-list\">';
              resultItems.forEach(function (result) {
                searchResultList += result.item;
              })
              searchResultList += "</ul>";
              resultContent.innerHTML = searchResultList;
            }
          }

          if ('auto' === 'auto') {
            input.addEventListener('input', inputEventFunction);
          } else {
            $('.search-icon').click(inputEventFunction);
            input.addEventListener('keypress', function (event) {
              if (event.keyCode === 13) {
                inputEventFunction();
              }
            });
          }

          // remove loading animation
          $(".local-search-pop-overlay").remove();
          $('body').css('overflow', '');

          proceedsearch();
        }
      });
    }

    // handle and trigger popup window;
    $('.popup-trigger').click(function(e) {
      e.stopPropagation();
      if (isfetched === false) {
        searchFunc(path, 'local-search-input', 'local-search-result');
      } else {
        proceedsearch();
      };
    });

    $('.popup-btn-close').click(onPopupClose);
    $('.popup').click(function(e){
      e.stopPropagation();
    });
    $(document).on('keyup', function (event) {
      var shouldDismissSearchPopup = event.which === 27 &&
        $('.search-popup').is(':visible');
      if (shouldDismissSearchPopup) {
        onPopupClose();
      }
    });
  </script>





  

  

  
<script>
(function(){
    var bp = document.createElement('script');
    var curProtocol = window.location.protocol.split(':')[0];
    if (curProtocol === 'https') {
        bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';        
    }
    else {
        bp.src = 'http://push.zhanzhang.baidu.com/push.js';
    }
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(bp, s);
})();
</script>


  
  
  
  <link rel="stylesheet" href="/blog/lib/needsharebutton/needsharebutton.css">

  
  
  <script src="/blog/lib/needsharebutton/needsharebutton.js"></script>

  <script>
    
      pbOptions = {};
      
          pbOptions.iconStyle = "box";
      
          pbOptions.boxForm = "horizontal";
      
          pbOptions.position = "bottomCenter";
      
          pbOptions.networks = "Weibo,Wechat,Douban,QQZone,Twitter,Facebook";
      
      new needShareButton('#needsharebutton-postbottom', pbOptions);
    
    
  </script>

  
  <script type="text/javascript">
  wpac_init = window.wpac_init || [];
  wpac_init.push({widget: 'Rating', id: 18607,
    el: 'wpac-rating',
    color: 'f79533'
  });
  (function() {
    if ('WIDGETPACK_LOADED' in window) return;
    WIDGETPACK_LOADED = true;
    var mc = document.createElement('script');
    mc.type = 'text/javascript';
    mc.async = true;
    mc.src = '//embed.widgetpack.com/widget.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(mc, s.nextSibling);
  })();
  </script>


  

  
<script>
  $('.highlight').each(function(i, e) {
    var $wrap = $('<div>').addClass('highlight-wrap');
    $(e).after($wrap);
    $wrap.append($('<button>').addClass('copy-btn').append('复制').on('click', function(e) {
      var code = $(this).parent().find('.code').find('.line').map(function(i, e) {
        return $(e).text();
      }).toArray().join('\n');
      var ta = document.createElement('textarea');
      var yPosition = window.pageYOffset || document.documentElement.scrollTop;
      ta.style.top = yPosition + 'px'; // Prevent page scroll
      ta.style.position = 'absolute';
      ta.style.opacity = '0';
      ta.readOnly = true;
      ta.value = code;
      document.body.appendChild(ta);
      ta.select();
      ta.setSelectionRange(0, code.length);
      ta.readOnly = false;
      var result = document.execCommand('copy');
      
        if (result) $(this).text('复制成功');
        else $(this).text('复制失败');
      
      ta.blur(); // For iOS
      $(this).blur();
    })).on('mouseleave', function(e) {
      var $b = $(this).find('.copy-btn');
      setTimeout(function() {
        $b.text('复制');
      }, 300);
    }).append(e);
  })
</script>


  

  

</body>
</html>
